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 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
400 if (op->IsRegister()) { | 400 if (op->IsRegister()) { |
401 return ToRegister(op->index()); | 401 return ToRegister(op->index()); |
402 } else if (op->IsConstantOperand()) { | 402 } else if (op->IsConstantOperand()) { |
403 LConstantOperand* const_op = LConstantOperand::cast(op); | 403 LConstantOperand* const_op = LConstantOperand::cast(op); |
404 HConstant* constant = chunk_->LookupConstant(const_op); | 404 HConstant* constant = chunk_->LookupConstant(const_op); |
405 Handle<Object> literal = constant->handle(); | 405 Handle<Object> literal = constant->handle(); |
406 Representation r = chunk_->LookupLiteralRepresentation(const_op); | 406 Representation r = chunk_->LookupLiteralRepresentation(const_op); |
407 if (r.IsInteger32()) { | 407 if (r.IsInteger32()) { |
408 ASSERT(literal->IsNumber()); | 408 ASSERT(literal->IsNumber()); |
409 __ li(scratch, Operand(static_cast<int32_t>(literal->Number()))); | 409 __ li(scratch, Operand(static_cast<int32_t>(literal->Number()))); |
| 410 } else if (r.IsSmi()) { |
| 411 ASSERT(constant->HasSmiValue()); |
| 412 __ li(scratch, Operand(Smi::FromInt(constant->Integer32Value()))); |
410 } else if (r.IsDouble()) { | 413 } else if (r.IsDouble()) { |
411 Abort("EmitLoadRegister: Unsupported double immediate."); | 414 Abort("EmitLoadRegister: Unsupported double immediate."); |
412 } else { | 415 } else { |
413 ASSERT(r.IsTagged()); | 416 ASSERT(r.IsTagged()); |
414 if (literal->IsSmi()) { | 417 __ LoadObject(scratch, literal); |
415 __ li(scratch, Operand(literal)); | |
416 } else { | |
417 __ LoadHeapObject(scratch, Handle<HeapObject>::cast(literal)); | |
418 } | |
419 } | 418 } |
420 return scratch; | 419 return scratch; |
421 } else if (op->IsStackSlot() || op->IsArgument()) { | 420 } else if (op->IsStackSlot() || op->IsArgument()) { |
422 __ lw(scratch, ToMemOperand(op)); | 421 __ lw(scratch, ToMemOperand(op)); |
423 return scratch; | 422 return scratch; |
424 } | 423 } |
425 UNREACHABLE(); | 424 UNREACHABLE(); |
426 return scratch; | 425 return scratch; |
427 } | 426 } |
428 | 427 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
474 bool LCodeGen::IsInteger32(LConstantOperand* op) const { | 473 bool LCodeGen::IsInteger32(LConstantOperand* op) const { |
475 return chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32(); | 474 return chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32(); |
476 } | 475 } |
477 | 476 |
478 | 477 |
479 bool LCodeGen::IsSmi(LConstantOperand* op) const { | 478 bool LCodeGen::IsSmi(LConstantOperand* op) const { |
480 return chunk_->LookupLiteralRepresentation(op).IsSmi(); | 479 return chunk_->LookupLiteralRepresentation(op).IsSmi(); |
481 } | 480 } |
482 | 481 |
483 | 482 |
484 int LCodeGen::ToInteger32(LConstantOperand* op) const { | 483 int32_t LCodeGen::ToInteger32(LConstantOperand* op) const { |
485 HConstant* constant = chunk_->LookupConstant(op); | 484 return ToRepresentation(op, Representation::Integer32()); |
486 return constant->Integer32Value(); | |
487 } | 485 } |
488 | 486 |
489 | 487 |
| 488 int32_t LCodeGen::ToRepresentation(LConstantOperand* op, |
| 489 const Representation& r) const { |
| 490 HConstant* constant = chunk_->LookupConstant(op); |
| 491 int32_t value = constant->Integer32Value(); |
| 492 if (r.IsInteger32()) return value; |
| 493 ASSERT(r.IsSmiOrTagged()); |
| 494 return reinterpret_cast<int32_t>(Smi::FromInt(value)); |
| 495 } |
| 496 |
| 497 |
490 Smi* LCodeGen::ToSmi(LConstantOperand* op) const { | 498 Smi* LCodeGen::ToSmi(LConstantOperand* op) const { |
491 HConstant* constant = chunk_->LookupConstant(op); | 499 HConstant* constant = chunk_->LookupConstant(op); |
492 return Smi::FromInt(constant->Integer32Value()); | 500 return Smi::FromInt(constant->Integer32Value()); |
493 } | 501 } |
494 | 502 |
495 | 503 |
496 double LCodeGen::ToDouble(LConstantOperand* op) const { | 504 double LCodeGen::ToDouble(LConstantOperand* op) const { |
497 HConstant* constant = chunk_->LookupConstant(op); | 505 HConstant* constant = chunk_->LookupConstant(op); |
498 ASSERT(constant->HasDoubleValue()); | 506 ASSERT(constant->HasDoubleValue()); |
499 return constant->DoubleValue(); | 507 return constant->DoubleValue(); |
500 } | 508 } |
501 | 509 |
502 | 510 |
503 Operand LCodeGen::ToOperand(LOperand* op) { | 511 Operand LCodeGen::ToOperand(LOperand* op) { |
504 if (op->IsConstantOperand()) { | 512 if (op->IsConstantOperand()) { |
505 LConstantOperand* const_op = LConstantOperand::cast(op); | 513 LConstantOperand* const_op = LConstantOperand::cast(op); |
506 HConstant* constant = chunk()->LookupConstant(const_op); | 514 HConstant* constant = chunk()->LookupConstant(const_op); |
507 Representation r = chunk_->LookupLiteralRepresentation(const_op); | 515 Representation r = chunk_->LookupLiteralRepresentation(const_op); |
508 if (r.IsInteger32()) { | 516 if (r.IsSmi()) { |
| 517 ASSERT(constant->HasSmiValue()); |
| 518 return Operand(Smi::FromInt(constant->Integer32Value())); |
| 519 } else if (r.IsInteger32()) { |
509 ASSERT(constant->HasInteger32Value()); | 520 ASSERT(constant->HasInteger32Value()); |
510 return Operand(constant->Integer32Value()); | 521 return Operand(constant->Integer32Value()); |
511 } else if (r.IsDouble()) { | 522 } else if (r.IsDouble()) { |
512 Abort("ToOperand Unsupported double immediate."); | 523 Abort("ToOperand Unsupported double immediate."); |
513 } | 524 } |
514 ASSERT(r.IsTagged()); | 525 ASSERT(r.IsTagged()); |
515 return Operand(constant->handle()); | 526 return Operand(constant->handle()); |
516 } else if (op->IsRegister()) { | 527 } else if (op->IsRegister()) { |
517 return Operand(ToRegister(op)); | 528 return Operand(ToRegister(op)); |
518 } else if (op->IsDoubleRegister()) { | 529 } else if (op->IsDoubleRegister()) { |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 LEnvironment* environment, | 794 LEnvironment* environment, |
784 Register src1, | 795 Register src1, |
785 const Operand& src2) { | 796 const Operand& src2) { |
786 Deoptimizer::BailoutType bailout_type = info()->IsStub() | 797 Deoptimizer::BailoutType bailout_type = info()->IsStub() |
787 ? Deoptimizer::LAZY | 798 ? Deoptimizer::LAZY |
788 : Deoptimizer::EAGER; | 799 : Deoptimizer::EAGER; |
789 DeoptimizeIf(cc, environment, bailout_type, src1, src2); | 800 DeoptimizeIf(cc, environment, bailout_type, src1, src2); |
790 } | 801 } |
791 | 802 |
792 | 803 |
793 void LCodeGen::SoftDeoptimize(LEnvironment* environment, | |
794 Register src1, | |
795 const Operand& src2) { | |
796 ASSERT(!info()->IsStub()); | |
797 DeoptimizeIf(al, environment, Deoptimizer::SOFT, src1, src2); | |
798 } | |
799 | |
800 | |
801 void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) { | 804 void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) { |
802 ZoneList<Handle<Map> > maps(1, zone()); | 805 ZoneList<Handle<Map> > maps(1, zone()); |
803 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | 806 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
804 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { | 807 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { |
805 RelocInfo::Mode mode = it.rinfo()->rmode(); | 808 RelocInfo::Mode mode = it.rinfo()->rmode(); |
806 if (mode == RelocInfo::EMBEDDED_OBJECT && | 809 if (mode == RelocInfo::EMBEDDED_OBJECT && |
807 it.rinfo()->target_object()->IsMap()) { | 810 it.rinfo()->target_object()->IsMap()) { |
808 Handle<Map> map(Map::cast(it.rinfo()->target_object())); | 811 Handle<Map> map(Map::cast(it.rinfo()->target_object())); |
809 if (map->CanTransition()) { | 812 if (map->CanTransition()) { |
810 maps.Add(map, zone()); | 813 maps.Add(map, zone()); |
(...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1372 // Note that result may alias left. | 1375 // Note that result may alias left. |
1373 Register left = ToRegister(instr->left()); | 1376 Register left = ToRegister(instr->left()); |
1374 LOperand* right_op = instr->right(); | 1377 LOperand* right_op = instr->right(); |
1375 | 1378 |
1376 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1379 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
1377 bool bailout_on_minus_zero = | 1380 bool bailout_on_minus_zero = |
1378 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); | 1381 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); |
1379 | 1382 |
1380 if (right_op->IsConstantOperand() && !can_overflow) { | 1383 if (right_op->IsConstantOperand() && !can_overflow) { |
1381 // Use optimized code for specific constants. | 1384 // Use optimized code for specific constants. |
1382 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); | 1385 int32_t constant = ToRepresentation( |
| 1386 LConstantOperand::cast(right_op), |
| 1387 instr->hydrogen()->right()->representation()); |
1383 | 1388 |
1384 if (bailout_on_minus_zero && (constant < 0)) { | 1389 if (bailout_on_minus_zero && (constant < 0)) { |
1385 // The case of a null constant will be handled separately. | 1390 // The case of a null constant will be handled separately. |
1386 // If constant is negative and left is null, the result should be -0. | 1391 // If constant is negative and left is null, the result should be -0. |
1387 DeoptimizeIf(eq, instr->environment(), left, Operand(zero_reg)); | 1392 DeoptimizeIf(eq, instr->environment(), left, Operand(zero_reg)); |
1388 } | 1393 } |
1389 | 1394 |
1390 switch (constant) { | 1395 switch (constant) { |
1391 case -1: | 1396 case -1: |
1392 __ Subu(result, zero_reg, left); | 1397 __ Subu(result, zero_reg, left); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1439 } | 1444 } |
1440 | 1445 |
1441 } else { | 1446 } else { |
1442 Register right = EmitLoadRegister(right_op, scratch); | 1447 Register right = EmitLoadRegister(right_op, scratch); |
1443 if (bailout_on_minus_zero) { | 1448 if (bailout_on_minus_zero) { |
1444 __ Or(ToRegister(instr->temp()), left, right); | 1449 __ Or(ToRegister(instr->temp()), left, right); |
1445 } | 1450 } |
1446 | 1451 |
1447 if (can_overflow) { | 1452 if (can_overflow) { |
1448 // hi:lo = left * right. | 1453 // hi:lo = left * right. |
1449 __ mult(left, right); | 1454 if (instr->hydrogen()->representation().IsSmi()) { |
1450 __ mfhi(scratch); | 1455 __ SmiUntag(result, left); |
1451 __ mflo(result); | 1456 __ mult(result, right); |
| 1457 __ mfhi(scratch); |
| 1458 __ mflo(result); |
| 1459 } else { |
| 1460 __ mult(left, right); |
| 1461 __ mfhi(scratch); |
| 1462 __ mflo(result); |
| 1463 } |
1452 __ sra(at, result, 31); | 1464 __ sra(at, result, 31); |
1453 DeoptimizeIf(ne, instr->environment(), scratch, Operand(at)); | 1465 DeoptimizeIf(ne, instr->environment(), scratch, Operand(at)); |
1454 } else { | 1466 } else { |
1455 __ Mul(result, left, right); | 1467 if (instr->hydrogen()->representation().IsSmi()) { |
| 1468 __ SmiUntag(result, left); |
| 1469 __ Mul(result, result, right); |
| 1470 } else { |
| 1471 __ Mul(result, left, right); |
| 1472 } |
1456 } | 1473 } |
1457 | 1474 |
1458 if (bailout_on_minus_zero) { | 1475 if (bailout_on_minus_zero) { |
1459 // Bail out if the result is supposed to be negative zero. | 1476 // Bail out if the result is supposed to be negative zero. |
1460 Label done; | 1477 Label done; |
1461 __ Branch(&done, ne, result, Operand(zero_reg)); | 1478 __ Branch(&done, ne, result, Operand(zero_reg)); |
1462 DeoptimizeIf(lt, | 1479 DeoptimizeIf(lt, |
1463 instr->environment(), | 1480 instr->environment(), |
1464 ToRegister(instr->temp()), | 1481 ToRegister(instr->temp()), |
1465 Operand(zero_reg)); | 1482 Operand(zero_reg)); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1500 } | 1517 } |
1501 } | 1518 } |
1502 | 1519 |
1503 | 1520 |
1504 void LCodeGen::DoShiftI(LShiftI* instr) { | 1521 void LCodeGen::DoShiftI(LShiftI* instr) { |
1505 // Both 'left' and 'right' are "used at start" (see LCodeGen::DoShift), so | 1522 // Both 'left' and 'right' are "used at start" (see LCodeGen::DoShift), so |
1506 // result may alias either of them. | 1523 // result may alias either of them. |
1507 LOperand* right_op = instr->right(); | 1524 LOperand* right_op = instr->right(); |
1508 Register left = ToRegister(instr->left()); | 1525 Register left = ToRegister(instr->left()); |
1509 Register result = ToRegister(instr->result()); | 1526 Register result = ToRegister(instr->result()); |
| 1527 Register scratch = scratch0(); |
1510 | 1528 |
1511 if (right_op->IsRegister()) { | 1529 if (right_op->IsRegister()) { |
1512 // No need to mask the right operand on MIPS, it is built into the variable | 1530 // No need to mask the right operand on MIPS, it is built into the variable |
1513 // shift instructions. | 1531 // shift instructions. |
1514 switch (instr->op()) { | 1532 switch (instr->op()) { |
1515 case Token::ROR: | 1533 case Token::ROR: |
1516 __ Ror(result, left, Operand(ToRegister(right_op))); | 1534 __ Ror(result, left, Operand(ToRegister(right_op))); |
1517 break; | 1535 break; |
1518 case Token::SAR: | 1536 case Token::SAR: |
1519 __ srav(result, left, ToRegister(right_op)); | 1537 __ srav(result, left, ToRegister(right_op)); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1556 } else { | 1574 } else { |
1557 if (instr->can_deopt()) { | 1575 if (instr->can_deopt()) { |
1558 __ And(at, left, Operand(0x80000000)); | 1576 __ And(at, left, Operand(0x80000000)); |
1559 DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg)); | 1577 DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg)); |
1560 } | 1578 } |
1561 __ Move(result, left); | 1579 __ Move(result, left); |
1562 } | 1580 } |
1563 break; | 1581 break; |
1564 case Token::SHL: | 1582 case Token::SHL: |
1565 if (shift_count != 0) { | 1583 if (shift_count != 0) { |
1566 __ sll(result, left, shift_count); | 1584 if (instr->hydrogen_value()->representation().IsSmi() && |
| 1585 instr->can_deopt()) { |
| 1586 __ sll(result, left, shift_count - 1); |
| 1587 __ SmiTagCheckOverflow(result, result, scratch); |
| 1588 DeoptimizeIf(lt, instr->environment(), scratch, Operand(zero_reg)); |
| 1589 } else { |
| 1590 __ sll(result, left, shift_count); |
| 1591 } |
1567 } else { | 1592 } else { |
1568 __ Move(result, left); | 1593 __ Move(result, left); |
1569 } | 1594 } |
1570 break; | 1595 break; |
1571 default: | 1596 default: |
1572 UNREACHABLE(); | 1597 UNREACHABLE(); |
1573 break; | 1598 break; |
1574 } | 1599 } |
1575 } | 1600 } |
1576 } | 1601 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1629 ASSERT(instr->result()->IsDoubleRegister()); | 1654 ASSERT(instr->result()->IsDoubleRegister()); |
1630 DoubleRegister result = ToDoubleRegister(instr->result()); | 1655 DoubleRegister result = ToDoubleRegister(instr->result()); |
1631 double v = instr->value(); | 1656 double v = instr->value(); |
1632 __ Move(result, v); | 1657 __ Move(result, v); |
1633 } | 1658 } |
1634 | 1659 |
1635 | 1660 |
1636 void LCodeGen::DoConstantT(LConstantT* instr) { | 1661 void LCodeGen::DoConstantT(LConstantT* instr) { |
1637 Handle<Object> value = instr->value(); | 1662 Handle<Object> value = instr->value(); |
1638 AllowDeferredHandleDereference smi_check; | 1663 AllowDeferredHandleDereference smi_check; |
1639 if (value->IsSmi()) { | 1664 __ LoadObject(ToRegister(instr->result()), value); |
1640 __ li(ToRegister(instr->result()), Operand(value)); | |
1641 } else { | |
1642 __ LoadHeapObject(ToRegister(instr->result()), | |
1643 Handle<HeapObject>::cast(value)); | |
1644 } | |
1645 } | 1665 } |
1646 | 1666 |
1647 | 1667 |
1648 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { | 1668 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { |
1649 Register result = ToRegister(instr->result()); | 1669 Register result = ToRegister(instr->result()); |
1650 Register map = ToRegister(instr->value()); | 1670 Register map = ToRegister(instr->value()); |
1651 __ EnumLength(result, map); | 1671 __ EnumLength(result, map); |
1652 } | 1672 } |
1653 | 1673 |
1654 | 1674 |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1813 DeoptimizeIf(lt, instr->environment(), overflow, Operand(zero_reg)); | 1833 DeoptimizeIf(lt, instr->environment(), overflow, Operand(zero_reg)); |
1814 } | 1834 } |
1815 } | 1835 } |
1816 | 1836 |
1817 | 1837 |
1818 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { | 1838 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
1819 LOperand* left = instr->left(); | 1839 LOperand* left = instr->left(); |
1820 LOperand* right = instr->right(); | 1840 LOperand* right = instr->right(); |
1821 HMathMinMax::Operation operation = instr->hydrogen()->operation(); | 1841 HMathMinMax::Operation operation = instr->hydrogen()->operation(); |
1822 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; | 1842 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; |
1823 if (instr->hydrogen()->representation().IsInteger32()) { | 1843 if (instr->hydrogen()->representation().IsSmiOrInteger32()) { |
1824 Register left_reg = ToRegister(left); | 1844 Register left_reg = ToRegister(left); |
1825 Operand right_op = (right->IsRegister() || right->IsConstantOperand()) | 1845 Operand right_op = (right->IsRegister() || right->IsConstantOperand()) |
1826 ? ToOperand(right) | 1846 ? ToOperand(right) |
1827 : Operand(EmitLoadRegister(right, at)); | 1847 : Operand(EmitLoadRegister(right, at)); |
1828 Register result_reg = ToRegister(instr->result()); | 1848 Register result_reg = ToRegister(instr->result()); |
1829 Label return_right, done; | 1849 Label return_right, done; |
1830 if (!result_reg.is(left_reg)) { | 1850 if (!result_reg.is(left_reg)) { |
1831 __ Branch(&return_right, NegateCondition(condition), left_reg, right_op); | 1851 __ Branch(&return_right, NegateCondition(condition), left_reg, right_op); |
1832 __ mov(result_reg, left_reg); | 1852 __ mov(result_reg, left_reg); |
1833 __ Branch(&done); | 1853 __ Branch(&done); |
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2233 | 2253 |
2234 | 2254 |
2235 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { | 2255 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { |
2236 Register left = ToRegister(instr->left()); | 2256 Register left = ToRegister(instr->left()); |
2237 Register right = ToRegister(instr->right()); | 2257 Register right = ToRegister(instr->right()); |
2238 | 2258 |
2239 EmitBranch(instr, eq, left, Operand(right)); | 2259 EmitBranch(instr, eq, left, Operand(right)); |
2240 } | 2260 } |
2241 | 2261 |
2242 | 2262 |
2243 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { | |
2244 Register left = ToRegister(instr->left()); | |
2245 | |
2246 EmitBranch(instr, eq, left, Operand(instr->hydrogen()->right())); | |
2247 } | |
2248 | |
2249 | |
2250 Condition LCodeGen::EmitIsObject(Register input, | 2263 Condition LCodeGen::EmitIsObject(Register input, |
2251 Register temp1, | 2264 Register temp1, |
2252 Register temp2, | 2265 Register temp2, |
2253 Label* is_not_object, | 2266 Label* is_not_object, |
2254 Label* is_object) { | 2267 Label* is_object) { |
2255 __ JumpIfSmi(input, is_not_object); | 2268 __ JumpIfSmi(input, is_not_object); |
2256 | 2269 |
2257 __ LoadRoot(temp2, Heap::kNullValueRootIndex); | 2270 __ LoadRoot(temp2, Heap::kNullValueRootIndex); |
2258 __ Branch(is_object, eq, input, Operand(temp2)); | 2271 __ Branch(is_object, eq, input, Operand(temp2)); |
2259 | 2272 |
(...skipping 634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2894 int offset = index * kPointerSize; | 2907 int offset = index * kPointerSize; |
2895 if (index < 0) { | 2908 if (index < 0) { |
2896 // Negative property indices are in-object properties, indexed | 2909 // Negative property indices are in-object properties, indexed |
2897 // from the end of the fixed part of the object. | 2910 // from the end of the fixed part of the object. |
2898 __ lw(result, FieldMemOperand(object, offset + type->instance_size())); | 2911 __ lw(result, FieldMemOperand(object, offset + type->instance_size())); |
2899 } else { | 2912 } else { |
2900 // Non-negative property indices are in the properties array. | 2913 // Non-negative property indices are in the properties array. |
2901 __ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 2914 __ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
2902 __ lw(result, FieldMemOperand(result, offset + FixedArray::kHeaderSize)); | 2915 __ lw(result, FieldMemOperand(result, offset + FixedArray::kHeaderSize)); |
2903 } | 2916 } |
2904 } else if (lookup.IsConstantFunction()) { | 2917 } else if (lookup.IsConstant()) { |
2905 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*type)); | 2918 Handle<Object> constant(lookup.GetConstantFromMap(*type), isolate()); |
2906 __ LoadHeapObject(result, function); | 2919 __ LoadObject(result, constant); |
2907 } else { | 2920 } else { |
2908 // Negative lookup. | 2921 // Negative lookup. |
2909 // Check prototypes. | 2922 // Check prototypes. |
2910 Handle<HeapObject> current(HeapObject::cast((*type)->prototype())); | 2923 Handle<HeapObject> current(HeapObject::cast((*type)->prototype())); |
2911 Heap* heap = type->GetHeap(); | 2924 Heap* heap = type->GetHeap(); |
2912 while (*current != heap->null_value()) { | 2925 while (*current != heap->null_value()) { |
2913 __ LoadHeapObject(result, current); | 2926 __ LoadHeapObject(result, current); |
2914 __ lw(result, FieldMemOperand(result, HeapObject::kMapOffset)); | 2927 __ lw(result, FieldMemOperand(result, HeapObject::kMapOffset)); |
2915 DeoptimizeIf(ne, env, result, Operand(Handle<Map>(current->map()))); | 2928 DeoptimizeIf(ne, env, result, Operand(Handle<Map>(current->map()))); |
2916 current = | 2929 current = |
(...skipping 1263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4180 | 4193 |
4181 // Name is always in a2. | 4194 // Name is always in a2. |
4182 __ li(a2, Operand(instr->name())); | 4195 __ li(a2, Operand(instr->name())); |
4183 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 4196 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
4184 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 4197 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
4185 : isolate()->builtins()->StoreIC_Initialize(); | 4198 : isolate()->builtins()->StoreIC_Initialize(); |
4186 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 4199 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
4187 } | 4200 } |
4188 | 4201 |
4189 | 4202 |
| 4203 void LCodeGen::ApplyCheckIf(Condition cc, |
| 4204 LBoundsCheck* check, |
| 4205 Register src1, |
| 4206 const Operand& src2) { |
| 4207 if (FLAG_debug_code && check->hydrogen()->skip_check()) { |
| 4208 Label done; |
| 4209 __ Branch(&done, NegateCondition(cc), src1, src2); |
| 4210 __ stop("eliminated bounds check failed"); |
| 4211 __ bind(&done); |
| 4212 } else { |
| 4213 DeoptimizeIf(cc, check->environment(), src1, src2); |
| 4214 } |
| 4215 } |
| 4216 |
| 4217 |
4190 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { | 4218 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
4191 if (instr->hydrogen()->skip_check()) return; | 4219 if (instr->hydrogen()->skip_check()) return; |
4192 | 4220 |
| 4221 Condition condition = instr->hydrogen()->allow_equality() ? hi : hs; |
4193 if (instr->index()->IsConstantOperand()) { | 4222 if (instr->index()->IsConstantOperand()) { |
4194 int constant_index = | 4223 int constant_index = |
4195 ToInteger32(LConstantOperand::cast(instr->index())); | 4224 ToInteger32(LConstantOperand::cast(instr->index())); |
4196 if (instr->hydrogen()->length()->representation().IsSmi()) { | 4225 if (instr->hydrogen()->length()->representation().IsSmi()) { |
4197 __ li(at, Operand(Smi::FromInt(constant_index))); | 4226 __ li(at, Operand(Smi::FromInt(constant_index))); |
4198 } else { | 4227 } else { |
4199 __ li(at, Operand(constant_index)); | 4228 __ li(at, Operand(constant_index)); |
4200 } | 4229 } |
4201 DeoptimizeIf(hs, | 4230 ApplyCheckIf(condition, |
4202 instr->environment(), | 4231 instr, |
4203 at, | 4232 at, |
4204 Operand(ToRegister(instr->length()))); | 4233 Operand(ToRegister(instr->length()))); |
4205 } else { | 4234 } else { |
4206 DeoptimizeIf(hs, | 4235 ApplyCheckIf(condition, |
4207 instr->environment(), | 4236 instr, |
4208 ToRegister(instr->index()), | 4237 ToRegister(instr->index()), |
4209 Operand(ToRegister(instr->length()))); | 4238 Operand(ToRegister(instr->length()))); |
4210 } | 4239 } |
4211 } | 4240 } |
4212 | 4241 |
4213 | 4242 |
4214 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { | 4243 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { |
4215 Register external_pointer = ToRegister(instr->elements()); | 4244 Register external_pointer = ToRegister(instr->elements()); |
4216 Register key = no_reg; | 4245 Register key = no_reg; |
4217 ElementsKind elements_kind = instr->elements_kind(); | 4246 ElementsKind elements_kind = instr->elements_kind(); |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4419 __ lw(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset)); | 4448 __ lw(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
4420 __ Branch(¬_applicable, ne, scratch, Operand(from_map)); | 4449 __ Branch(¬_applicable, ne, scratch, Operand(from_map)); |
4421 | 4450 |
4422 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { | 4451 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { |
4423 Register new_map_reg = ToRegister(instr->new_map_temp()); | 4452 Register new_map_reg = ToRegister(instr->new_map_temp()); |
4424 __ li(new_map_reg, Operand(to_map)); | 4453 __ li(new_map_reg, Operand(to_map)); |
4425 __ sw(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset)); | 4454 __ sw(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
4426 // Write barrier. | 4455 // Write barrier. |
4427 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, | 4456 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, |
4428 scratch, GetRAState(), kDontSaveFPRegs); | 4457 scratch, GetRAState(), kDontSaveFPRegs); |
4429 } else if (FLAG_compiled_transitions) { | 4458 } else { |
4430 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4459 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
4431 __ mov(a0, object_reg); | 4460 __ mov(a0, object_reg); |
4432 __ li(a1, Operand(to_map)); | 4461 __ li(a1, Operand(to_map)); |
4433 TransitionElementsKindStub stub(from_kind, to_kind); | 4462 TransitionElementsKindStub stub(from_kind, to_kind); |
4434 __ CallStub(&stub); | 4463 __ CallStub(&stub); |
4435 RecordSafepointWithRegisters( | 4464 RecordSafepointWithRegisters( |
4436 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 4465 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
4437 } else if (IsFastSmiElementsKind(from_kind) && | |
4438 IsFastDoubleElementsKind(to_kind)) { | |
4439 Register fixed_object_reg = ToRegister(instr->temp()); | |
4440 ASSERT(fixed_object_reg.is(a2)); | |
4441 Register new_map_reg = ToRegister(instr->new_map_temp()); | |
4442 ASSERT(new_map_reg.is(a3)); | |
4443 __ li(new_map_reg, Operand(to_map)); | |
4444 __ mov(fixed_object_reg, object_reg); | |
4445 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), | |
4446 RelocInfo::CODE_TARGET, instr); | |
4447 } else if (IsFastDoubleElementsKind(from_kind) && | |
4448 IsFastObjectElementsKind(to_kind)) { | |
4449 Register fixed_object_reg = ToRegister(instr->temp()); | |
4450 ASSERT(fixed_object_reg.is(a2)); | |
4451 Register new_map_reg = ToRegister(instr->new_map_temp()); | |
4452 ASSERT(new_map_reg.is(a3)); | |
4453 __ li(new_map_reg, Operand(to_map)); | |
4454 __ mov(fixed_object_reg, object_reg); | |
4455 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), | |
4456 RelocInfo::CODE_TARGET, instr); | |
4457 } else { | |
4458 UNREACHABLE(); | |
4459 } | 4466 } |
4460 __ bind(¬_applicable); | 4467 __ bind(¬_applicable); |
4461 } | 4468 } |
4462 | 4469 |
4463 | 4470 |
4464 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { | 4471 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { |
4465 Register object = ToRegister(instr->object()); | 4472 Register object = ToRegister(instr->object()); |
4466 Register temp = ToRegister(instr->temp()); | 4473 Register temp = ToRegister(instr->temp()); |
4467 Label fail; | 4474 Label fail; |
4468 __ TestJSArrayForAllocationMemento(object, temp, ne, &fail); | 4475 __ TestJSArrayForAllocationMemento(object, temp, ne, &fail); |
(...skipping 719 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5188 Handle<Map> map, | 5195 Handle<Map> map, |
5189 LEnvironment* env) { | 5196 LEnvironment* env) { |
5190 Label success; | 5197 Label success; |
5191 __ CompareMapAndBranch(map_reg, map, &success, eq, &success); | 5198 __ CompareMapAndBranch(map_reg, map, &success, eq, &success); |
5192 DeoptimizeIf(al, env); | 5199 DeoptimizeIf(al, env); |
5193 __ bind(&success); | 5200 __ bind(&success); |
5194 } | 5201 } |
5195 | 5202 |
5196 | 5203 |
5197 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 5204 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
| 5205 if (instr->hydrogen()->CanOmitMapChecks()) return; |
5198 Register map_reg = scratch0(); | 5206 Register map_reg = scratch0(); |
5199 LOperand* input = instr->value(); | 5207 LOperand* input = instr->value(); |
5200 ASSERT(input->IsRegister()); | 5208 ASSERT(input->IsRegister()); |
5201 Register reg = ToRegister(input); | 5209 Register reg = ToRegister(input); |
5202 Label success; | 5210 Label success; |
5203 SmallMapList* map_set = instr->hydrogen()->map_set(); | 5211 SmallMapList* map_set = instr->hydrogen()->map_set(); |
5204 __ lw(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); | 5212 __ lw(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); |
5205 for (int i = 0; i < map_set->length() - 1; i++) { | 5213 for (int i = 0; i < map_set->length() - 1; i++) { |
5206 Handle<Map> map = map_set->at(i); | 5214 Handle<Map> map = map_set->at(i); |
5207 __ CompareMapAndBranch(map_reg, map, &success, eq, &success); | 5215 __ CompareMapAndBranch(map_reg, map, &success, eq, &success); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5256 __ jmp(&done); | 5264 __ jmp(&done); |
5257 | 5265 |
5258 __ bind(&is_smi); | 5266 __ bind(&is_smi); |
5259 __ ClampUint8(result_reg, scratch); | 5267 __ ClampUint8(result_reg, scratch); |
5260 | 5268 |
5261 __ bind(&done); | 5269 __ bind(&done); |
5262 } | 5270 } |
5263 | 5271 |
5264 | 5272 |
5265 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { | 5273 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { |
| 5274 if (instr->hydrogen()->CanOmitPrototypeChecks()) return; |
| 5275 |
5266 Register prototype_reg = ToRegister(instr->temp()); | 5276 Register prototype_reg = ToRegister(instr->temp()); |
5267 Register map_reg = ToRegister(instr->temp2()); | 5277 Register map_reg = ToRegister(instr->temp2()); |
5268 | 5278 |
5269 ZoneList<Handle<JSObject> >* prototypes = instr->prototypes(); | 5279 ZoneList<Handle<JSObject> >* prototypes = instr->prototypes(); |
5270 ZoneList<Handle<Map> >* maps = instr->maps(); | 5280 ZoneList<Handle<Map> >* maps = instr->maps(); |
5271 | 5281 |
5272 ASSERT(prototypes->length() == maps->length()); | 5282 ASSERT(prototypes->length() == maps->length()); |
5273 | 5283 |
5274 if (!instr->hydrogen()->CanOmitPrototypeChecks()) { | 5284 for (int i = 0; i < prototypes->length(); i++) { |
5275 for (int i = 0; i < prototypes->length(); i++) { | 5285 __ LoadHeapObject(prototype_reg, prototypes->at(i)); |
5276 __ LoadHeapObject(prototype_reg, prototypes->at(i)); | 5286 __ lw(map_reg, FieldMemOperand(prototype_reg, HeapObject::kMapOffset)); |
5277 __ lw(map_reg, FieldMemOperand(prototype_reg, HeapObject::kMapOffset)); | 5287 DoCheckMapCommon(map_reg, maps->at(i), instr->environment()); |
5278 DoCheckMapCommon(map_reg, maps->at(i), instr->environment()); | |
5279 } | |
5280 } | 5288 } |
5281 } | 5289 } |
5282 | 5290 |
5283 | 5291 |
5284 void LCodeGen::DoAllocate(LAllocate* instr) { | 5292 void LCodeGen::DoAllocate(LAllocate* instr) { |
5285 class DeferredAllocate: public LDeferredCode { | 5293 class DeferredAllocate: public LDeferredCode { |
5286 public: | 5294 public: |
5287 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) | 5295 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) |
5288 : LDeferredCode(codegen), instr_(instr) { } | 5296 : LDeferredCode(codegen), instr_(instr) { } |
5289 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); } | 5297 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); } |
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5642 EnsureSpaceForLazyDeopt(); | 5650 EnsureSpaceForLazyDeopt(); |
5643 last_lazy_deopt_pc_ = masm()->pc_offset(); | 5651 last_lazy_deopt_pc_ = masm()->pc_offset(); |
5644 ASSERT(instr->HasEnvironment()); | 5652 ASSERT(instr->HasEnvironment()); |
5645 LEnvironment* env = instr->environment(); | 5653 LEnvironment* env = instr->environment(); |
5646 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 5654 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
5647 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 5655 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
5648 } | 5656 } |
5649 | 5657 |
5650 | 5658 |
5651 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { | 5659 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { |
5652 if (instr->hydrogen_value()->IsSoftDeoptimize()) { | 5660 Deoptimizer::BailoutType type = instr->hydrogen()->type(); |
5653 SoftDeoptimize(instr->environment(), zero_reg, Operand(zero_reg)); | 5661 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the |
5654 } else { | 5662 // needed return address), even though the implementation of LAZY and EAGER is |
5655 DeoptimizeIf(al, instr->environment(), zero_reg, Operand(zero_reg)); | 5663 // now identical. When LAZY is eventually completely folded into EAGER, remove |
| 5664 // the special case below. |
| 5665 if (info()->IsStub() && type == Deoptimizer::EAGER) { |
| 5666 type = Deoptimizer::LAZY; |
5656 } | 5667 } |
| 5668 DeoptimizeIf(al, instr->environment(), type, zero_reg, Operand(zero_reg)); |
5657 } | 5669 } |
5658 | 5670 |
5659 | 5671 |
5660 void LCodeGen::DoDummyUse(LDummyUse* instr) { | 5672 void LCodeGen::DoDummyUse(LDummyUse* instr) { |
5661 // Nothing to see here, move on! | 5673 // Nothing to see here, move on! |
5662 } | 5674 } |
5663 | 5675 |
5664 | 5676 |
5665 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { | 5677 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { |
5666 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 5678 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5824 __ Subu(scratch, result, scratch); | 5836 __ Subu(scratch, result, scratch); |
5825 __ lw(result, FieldMemOperand(scratch, | 5837 __ lw(result, FieldMemOperand(scratch, |
5826 FixedArray::kHeaderSize - kPointerSize)); | 5838 FixedArray::kHeaderSize - kPointerSize)); |
5827 __ bind(&done); | 5839 __ bind(&done); |
5828 } | 5840 } |
5829 | 5841 |
5830 | 5842 |
5831 #undef __ | 5843 #undef __ |
5832 | 5844 |
5833 } } // namespace v8::internal | 5845 } } // namespace v8::internal |
OLD | NEW |