OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1360 __ j(cc, chunk_->GetAssemblyLabel(left_block)); | 1360 __ j(cc, chunk_->GetAssemblyLabel(left_block)); |
1361 __ jmp(chunk_->GetAssemblyLabel(right_block)); | 1361 __ jmp(chunk_->GetAssemblyLabel(right_block)); |
1362 } | 1362 } |
1363 } | 1363 } |
1364 | 1364 |
1365 | 1365 |
1366 void LCodeGen::DoBranch(LBranch* instr) { | 1366 void LCodeGen::DoBranch(LBranch* instr) { |
1367 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1367 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1368 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1368 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1369 | 1369 |
1370 Representation r = instr->hydrogen()->representation(); | 1370 Representation r = instr->hydrogen()->value()->representation(); |
1371 if (r.IsInteger32()) { | 1371 if (r.IsInteger32()) { |
1372 Register reg = ToRegister(instr->InputAt(0)); | 1372 Register reg = ToRegister(instr->InputAt(0)); |
1373 __ test(reg, Operand(reg)); | 1373 __ test(reg, Operand(reg)); |
1374 EmitBranch(true_block, false_block, not_zero); | 1374 EmitBranch(true_block, false_block, not_zero); |
1375 } else if (r.IsDouble()) { | 1375 } else if (r.IsDouble()) { |
1376 XMMRegister reg = ToDoubleRegister(instr->InputAt(0)); | 1376 XMMRegister reg = ToDoubleRegister(instr->InputAt(0)); |
1377 __ xorps(xmm0, xmm0); | 1377 __ xorps(xmm0, xmm0); |
1378 __ ucomisd(reg, xmm0); | 1378 __ ucomisd(reg, xmm0); |
1379 EmitBranch(true_block, false_block, not_equal); | 1379 EmitBranch(true_block, false_block, not_equal); |
1380 } else { | 1380 } else { |
1381 ASSERT(r.IsTagged()); | 1381 ASSERT(r.IsTagged()); |
1382 Register reg = ToRegister(instr->InputAt(0)); | 1382 Register reg = ToRegister(instr->InputAt(0)); |
1383 if (instr->hydrogen()->type().IsBoolean()) { | 1383 if (instr->hydrogen()->value()->type().IsBoolean()) { |
1384 __ cmp(reg, factory()->true_value()); | 1384 __ cmp(reg, factory()->true_value()); |
1385 EmitBranch(true_block, false_block, equal); | 1385 EmitBranch(true_block, false_block, equal); |
1386 } else { | 1386 } else { |
1387 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1387 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1388 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1388 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1389 | 1389 |
1390 __ cmp(reg, factory()->undefined_value()); | 1390 __ cmp(reg, factory()->undefined_value()); |
1391 __ j(equal, false_label); | 1391 __ j(equal, false_label); |
1392 __ cmp(reg, factory()->true_value()); | 1392 __ cmp(reg, factory()->true_value()); |
1393 __ j(equal, true_label); | 1393 __ j(equal, true_label); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1467 | 1467 |
1468 void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) { | 1468 void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) { |
1469 if (right->IsConstantOperand()) { | 1469 if (right->IsConstantOperand()) { |
1470 __ cmp(ToOperand(left), ToImmediate(right)); | 1470 __ cmp(ToOperand(left), ToImmediate(right)); |
1471 } else { | 1471 } else { |
1472 __ cmp(ToRegister(left), ToOperand(right)); | 1472 __ cmp(ToRegister(left), ToOperand(right)); |
1473 } | 1473 } |
1474 } | 1474 } |
1475 | 1475 |
1476 | 1476 |
1477 void LCodeGen::DoCmpID(LCmpID* instr) { | |
1478 LOperand* left = instr->InputAt(0); | |
1479 LOperand* right = instr->InputAt(1); | |
1480 LOperand* result = instr->result(); | |
1481 | |
1482 Label unordered; | |
1483 if (instr->is_double()) { | |
1484 // Don't base result on EFLAGS when a NaN is involved. Instead | |
1485 // jump to the unordered case, which produces a false value. | |
1486 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); | |
1487 __ j(parity_even, &unordered, Label::kNear); | |
1488 } else { | |
1489 EmitCmpI(left, right); | |
1490 } | |
1491 | |
1492 Label done; | |
1493 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | |
1494 __ mov(ToRegister(result), factory()->true_value()); | |
1495 __ j(cc, &done, Label::kNear); | |
1496 | |
1497 __ bind(&unordered); | |
1498 __ mov(ToRegister(result), factory()->false_value()); | |
1499 __ bind(&done); | |
1500 } | |
1501 | |
1502 | |
1503 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 1477 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
1504 LOperand* left = instr->InputAt(0); | 1478 LOperand* left = instr->InputAt(0); |
1505 LOperand* right = instr->InputAt(1); | 1479 LOperand* right = instr->InputAt(1); |
1506 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1480 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1507 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1481 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1508 | 1482 |
1509 if (instr->is_double()) { | 1483 if (instr->is_double()) { |
1510 // Don't base result on EFLAGS when a NaN is involved. Instead | 1484 // Don't base result on EFLAGS when a NaN is involved. Instead |
1511 // jump to the false block. | 1485 // jump to the false block. |
1512 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); | 1486 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); |
1513 __ j(parity_even, chunk_->GetAssemblyLabel(false_block)); | 1487 __ j(parity_even, chunk_->GetAssemblyLabel(false_block)); |
1514 } else { | 1488 } else { |
1515 EmitCmpI(left, right); | 1489 EmitCmpI(left, right); |
1516 } | 1490 } |
1517 | 1491 |
1518 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | 1492 Condition cc = TokenToCondition(instr->op(), instr->is_double()); |
1519 EmitBranch(true_block, false_block, cc); | 1493 EmitBranch(true_block, false_block, cc); |
1520 } | 1494 } |
1521 | 1495 |
1522 | 1496 |
1523 void LCodeGen::DoCmpObjectEq(LCmpObjectEq* instr) { | |
1524 Register left = ToRegister(instr->InputAt(0)); | |
1525 Register right = ToRegister(instr->InputAt(1)); | |
1526 Register result = ToRegister(instr->result()); | |
1527 | |
1528 __ cmp(left, Operand(right)); | |
1529 __ mov(result, factory()->true_value()); | |
1530 Label done; | |
1531 __ j(equal, &done, Label::kNear); | |
1532 __ mov(result, factory()->false_value()); | |
1533 __ bind(&done); | |
1534 } | |
1535 | |
1536 | |
1537 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { | 1497 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { |
1538 Register left = ToRegister(instr->InputAt(0)); | 1498 Register left = ToRegister(instr->InputAt(0)); |
1539 Register right = ToRegister(instr->InputAt(1)); | 1499 Register right = ToRegister(instr->InputAt(1)); |
1540 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1500 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1541 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1501 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1542 | 1502 |
1543 __ cmp(left, Operand(right)); | 1503 __ cmp(left, Operand(right)); |
1544 EmitBranch(true_block, false_block, equal); | 1504 EmitBranch(true_block, false_block, equal); |
1545 } | 1505 } |
1546 | 1506 |
1547 | 1507 |
1548 void LCodeGen::DoCmpConstantEq(LCmpConstantEq* instr) { | |
1549 Register left = ToRegister(instr->InputAt(0)); | |
1550 Register result = ToRegister(instr->result()); | |
1551 | |
1552 Label done; | |
1553 __ cmp(left, instr->hydrogen()->right()); | |
1554 __ mov(result, factory()->true_value()); | |
1555 __ j(equal, &done, Label::kNear); | |
1556 __ mov(result, factory()->false_value()); | |
1557 __ bind(&done); | |
1558 } | |
1559 | |
1560 | |
1561 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { | 1508 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { |
1562 Register left = ToRegister(instr->InputAt(0)); | 1509 Register left = ToRegister(instr->InputAt(0)); |
1563 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1510 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1564 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1511 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1565 | 1512 |
1566 __ cmp(left, instr->hydrogen()->right()); | 1513 __ cmp(left, instr->hydrogen()->right()); |
1567 EmitBranch(true_block, false_block, equal); | 1514 EmitBranch(true_block, false_block, equal); |
1568 } | 1515 } |
1569 | 1516 |
1570 | 1517 |
1571 void LCodeGen::DoIsNull(LIsNull* instr) { | |
1572 Register reg = ToRegister(instr->InputAt(0)); | |
1573 Register result = ToRegister(instr->result()); | |
1574 | |
1575 // TODO(fsc): If the expression is known to be a smi, then it's | |
1576 // definitely not null. Materialize false. | |
1577 | |
1578 __ cmp(reg, factory()->null_value()); | |
1579 if (instr->is_strict()) { | |
1580 __ mov(result, factory()->true_value()); | |
1581 Label done; | |
1582 __ j(equal, &done, Label::kNear); | |
1583 __ mov(result, factory()->false_value()); | |
1584 __ bind(&done); | |
1585 } else { | |
1586 Label true_value, false_value, done; | |
1587 __ j(equal, &true_value, Label::kNear); | |
1588 __ cmp(reg, factory()->undefined_value()); | |
1589 __ j(equal, &true_value, Label::kNear); | |
1590 __ JumpIfSmi(reg, &false_value, Label::kNear); | |
1591 // Check for undetectable objects by looking in the bit field in | |
1592 // the map. The object has already been smi checked. | |
1593 Register scratch = result; | |
1594 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | |
1595 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); | |
1596 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); | |
1597 __ j(not_zero, &true_value, Label::kNear); | |
1598 __ bind(&false_value); | |
1599 __ mov(result, factory()->false_value()); | |
1600 __ jmp(&done, Label::kNear); | |
1601 __ bind(&true_value); | |
1602 __ mov(result, factory()->true_value()); | |
1603 __ bind(&done); | |
1604 } | |
1605 } | |
1606 | |
1607 | |
1608 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { | 1518 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { |
1609 Register reg = ToRegister(instr->InputAt(0)); | 1519 Register reg = ToRegister(instr->InputAt(0)); |
1610 | 1520 |
1611 // TODO(fsc): If the expression is known to be a smi, then it's | 1521 // TODO(fsc): If the expression is known to be a smi, then it's |
1612 // definitely not null. Jump to the false block. | 1522 // definitely not null. Jump to the false block. |
1613 | 1523 |
1614 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1524 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1615 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1525 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1616 | 1526 |
1617 __ cmp(reg, factory()->null_value()); | 1527 __ cmp(reg, factory()->null_value()); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1651 __ j(not_zero, is_not_object); | 1561 __ j(not_zero, is_not_object); |
1652 | 1562 |
1653 __ movzx_b(temp1, FieldOperand(temp1, Map::kInstanceTypeOffset)); | 1563 __ movzx_b(temp1, FieldOperand(temp1, Map::kInstanceTypeOffset)); |
1654 __ cmp(temp1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); | 1564 __ cmp(temp1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); |
1655 __ j(below, is_not_object); | 1565 __ j(below, is_not_object); |
1656 __ cmp(temp1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); | 1566 __ cmp(temp1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
1657 return below_equal; | 1567 return below_equal; |
1658 } | 1568 } |
1659 | 1569 |
1660 | 1570 |
1661 void LCodeGen::DoIsObject(LIsObject* instr) { | |
1662 Register reg = ToRegister(instr->InputAt(0)); | |
1663 Register result = ToRegister(instr->result()); | |
1664 Label is_false, is_true, done; | |
1665 | |
1666 Condition true_cond = EmitIsObject(reg, result, &is_false, &is_true); | |
1667 __ j(true_cond, &is_true); | |
1668 | |
1669 __ bind(&is_false); | |
1670 __ mov(result, factory()->false_value()); | |
1671 __ jmp(&done); | |
1672 | |
1673 __ bind(&is_true); | |
1674 __ mov(result, factory()->true_value()); | |
1675 | |
1676 __ bind(&done); | |
1677 } | |
1678 | |
1679 | |
1680 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 1571 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
1681 Register reg = ToRegister(instr->InputAt(0)); | 1572 Register reg = ToRegister(instr->InputAt(0)); |
1682 Register temp = ToRegister(instr->TempAt(0)); | 1573 Register temp = ToRegister(instr->TempAt(0)); |
1683 | 1574 |
1684 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1575 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1685 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1576 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1686 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1577 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1687 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1578 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1688 | 1579 |
1689 Condition true_cond = EmitIsObject(reg, temp, false_label, true_label); | 1580 Condition true_cond = EmitIsObject(reg, temp, false_label, true_label); |
1690 | 1581 |
1691 EmitBranch(true_block, false_block, true_cond); | 1582 EmitBranch(true_block, false_block, true_cond); |
1692 } | 1583 } |
1693 | 1584 |
1694 | 1585 |
1695 void LCodeGen::DoIsSmi(LIsSmi* instr) { | |
1696 Operand input = ToOperand(instr->InputAt(0)); | |
1697 Register result = ToRegister(instr->result()); | |
1698 | |
1699 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | |
1700 Label done; | |
1701 __ mov(result, factory()->true_value()); | |
1702 __ JumpIfSmi(input, &done, Label::kNear); | |
1703 __ mov(result, factory()->false_value()); | |
1704 __ bind(&done); | |
1705 } | |
1706 | |
1707 | |
1708 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 1586 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
1709 Operand input = ToOperand(instr->InputAt(0)); | 1587 Operand input = ToOperand(instr->InputAt(0)); |
1710 | 1588 |
1711 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1589 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1712 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1590 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1713 | 1591 |
1714 __ test(input, Immediate(kSmiTagMask)); | 1592 __ test(input, Immediate(kSmiTagMask)); |
1715 EmitBranch(true_block, false_block, zero); | 1593 EmitBranch(true_block, false_block, zero); |
1716 } | 1594 } |
1717 | 1595 |
1718 | 1596 |
1719 void LCodeGen::DoIsUndetectable(LIsUndetectable* instr) { | |
1720 Register input = ToRegister(instr->InputAt(0)); | |
1721 Register result = ToRegister(instr->result()); | |
1722 | |
1723 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | |
1724 Label false_label, done; | |
1725 STATIC_ASSERT(kSmiTag == 0); | |
1726 __ JumpIfSmi(input, &false_label, Label::kNear); | |
1727 __ mov(result, FieldOperand(input, HeapObject::kMapOffset)); | |
1728 __ test_b(FieldOperand(result, Map::kBitFieldOffset), | |
1729 1 << Map::kIsUndetectable); | |
1730 __ j(zero, &false_label, Label::kNear); | |
1731 __ mov(result, factory()->true_value()); | |
1732 __ jmp(&done); | |
1733 __ bind(&false_label); | |
1734 __ mov(result, factory()->false_value()); | |
1735 __ bind(&done); | |
1736 } | |
1737 | |
1738 | |
1739 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { | 1597 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { |
1740 Register input = ToRegister(instr->InputAt(0)); | 1598 Register input = ToRegister(instr->InputAt(0)); |
1741 Register temp = ToRegister(instr->TempAt(0)); | 1599 Register temp = ToRegister(instr->TempAt(0)); |
1742 | 1600 |
1743 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1601 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1744 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1602 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1745 | 1603 |
1746 STATIC_ASSERT(kSmiTag == 0); | 1604 STATIC_ASSERT(kSmiTag == 0); |
1747 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); | 1605 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); |
1748 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); | 1606 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); |
1749 __ test_b(FieldOperand(temp, Map::kBitFieldOffset), | 1607 __ test_b(FieldOperand(temp, Map::kBitFieldOffset), |
1750 1 << Map::kIsUndetectable); | 1608 1 << Map::kIsUndetectable); |
1751 EmitBranch(true_block, false_block, not_zero); | 1609 EmitBranch(true_block, false_block, not_zero); |
1752 } | 1610 } |
1753 | 1611 |
1754 | 1612 |
1755 static InstanceType TestType(HHasInstanceType* instr) { | 1613 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { |
1756 InstanceType from = instr->from(); | 1614 InstanceType from = instr->from(); |
1757 InstanceType to = instr->to(); | 1615 InstanceType to = instr->to(); |
1758 if (from == FIRST_TYPE) return to; | 1616 if (from == FIRST_TYPE) return to; |
1759 ASSERT(from == to || to == LAST_TYPE); | 1617 ASSERT(from == to || to == LAST_TYPE); |
1760 return from; | 1618 return from; |
1761 } | 1619 } |
1762 | 1620 |
1763 | 1621 |
1764 static Condition BranchCondition(HHasInstanceType* instr) { | 1622 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { |
1765 InstanceType from = instr->from(); | 1623 InstanceType from = instr->from(); |
1766 InstanceType to = instr->to(); | 1624 InstanceType to = instr->to(); |
1767 if (from == to) return equal; | 1625 if (from == to) return equal; |
1768 if (to == LAST_TYPE) return above_equal; | 1626 if (to == LAST_TYPE) return above_equal; |
1769 if (from == FIRST_TYPE) return below_equal; | 1627 if (from == FIRST_TYPE) return below_equal; |
1770 UNREACHABLE(); | 1628 UNREACHABLE(); |
1771 return equal; | 1629 return equal; |
1772 } | 1630 } |
1773 | 1631 |
1774 | 1632 |
1775 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { | |
1776 Register input = ToRegister(instr->InputAt(0)); | |
1777 Register result = ToRegister(instr->result()); | |
1778 | |
1779 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | |
1780 Label done, is_false; | |
1781 __ JumpIfSmi(input, &is_false, Label::kNear); | |
1782 __ CmpObjectType(input, TestType(instr->hydrogen()), result); | |
1783 __ j(NegateCondition(BranchCondition(instr->hydrogen())), | |
1784 &is_false, Label::kNear); | |
1785 __ mov(result, factory()->true_value()); | |
1786 __ jmp(&done, Label::kNear); | |
1787 __ bind(&is_false); | |
1788 __ mov(result, factory()->false_value()); | |
1789 __ bind(&done); | |
1790 } | |
1791 | |
1792 | |
1793 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 1633 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
1794 Register input = ToRegister(instr->InputAt(0)); | 1634 Register input = ToRegister(instr->InputAt(0)); |
1795 Register temp = ToRegister(instr->TempAt(0)); | 1635 Register temp = ToRegister(instr->TempAt(0)); |
1796 | 1636 |
1797 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1637 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1798 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1638 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1799 | 1639 |
1800 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1640 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1801 | 1641 |
1802 __ JumpIfSmi(input, false_label); | 1642 __ JumpIfSmi(input, false_label); |
1803 | 1643 |
1804 __ CmpObjectType(input, TestType(instr->hydrogen()), temp); | 1644 __ CmpObjectType(input, TestType(instr->hydrogen()), temp); |
1805 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); | 1645 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); |
1806 } | 1646 } |
1807 | 1647 |
1808 | 1648 |
1809 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { | 1649 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { |
1810 Register input = ToRegister(instr->InputAt(0)); | 1650 Register input = ToRegister(instr->InputAt(0)); |
1811 Register result = ToRegister(instr->result()); | 1651 Register result = ToRegister(instr->result()); |
1812 | 1652 |
1813 if (FLAG_debug_code) { | 1653 if (FLAG_debug_code) { |
1814 __ AbortIfNotString(input); | 1654 __ AbortIfNotString(input); |
1815 } | 1655 } |
1816 | 1656 |
1817 __ mov(result, FieldOperand(input, String::kHashFieldOffset)); | 1657 __ mov(result, FieldOperand(input, String::kHashFieldOffset)); |
1818 __ IndexFromHash(result, result); | 1658 __ IndexFromHash(result, result); |
1819 } | 1659 } |
1820 | 1660 |
1821 | 1661 |
1822 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { | |
1823 Register input = ToRegister(instr->InputAt(0)); | |
1824 Register result = ToRegister(instr->result()); | |
1825 | |
1826 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | |
1827 __ mov(result, factory()->true_value()); | |
1828 __ test(FieldOperand(input, String::kHashFieldOffset), | |
1829 Immediate(String::kContainsCachedArrayIndexMask)); | |
1830 Label done; | |
1831 __ j(zero, &done, Label::kNear); | |
1832 __ mov(result, factory()->false_value()); | |
1833 __ bind(&done); | |
1834 } | |
1835 | |
1836 | |
1837 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 1662 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
1838 LHasCachedArrayIndexAndBranch* instr) { | 1663 LHasCachedArrayIndexAndBranch* instr) { |
1839 Register input = ToRegister(instr->InputAt(0)); | 1664 Register input = ToRegister(instr->InputAt(0)); |
1840 | 1665 |
1841 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1666 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1842 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1667 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1843 | 1668 |
1844 __ test(FieldOperand(input, String::kHashFieldOffset), | 1669 __ test(FieldOperand(input, String::kHashFieldOffset), |
1845 Immediate(String::kContainsCachedArrayIndexMask)); | 1670 Immediate(String::kContainsCachedArrayIndexMask)); |
1846 EmitBranch(true_block, false_block, equal); | 1671 EmitBranch(true_block, false_block, equal); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1897 // The name in the constructor is a symbol because of the way the context is | 1722 // The name in the constructor is a symbol because of the way the context is |
1898 // booted. This routine isn't expected to work for random API-created | 1723 // booted. This routine isn't expected to work for random API-created |
1899 // classes and it doesn't have to because you can't access it with natives | 1724 // classes and it doesn't have to because you can't access it with natives |
1900 // syntax. Since both sides are symbols it is sufficient to use an identity | 1725 // syntax. Since both sides are symbols it is sufficient to use an identity |
1901 // comparison. | 1726 // comparison. |
1902 __ cmp(temp, class_name); | 1727 __ cmp(temp, class_name); |
1903 // End with the answer in the z flag. | 1728 // End with the answer in the z flag. |
1904 } | 1729 } |
1905 | 1730 |
1906 | 1731 |
1907 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { | |
1908 Register input = ToRegister(instr->InputAt(0)); | |
1909 Register result = ToRegister(instr->result()); | |
1910 ASSERT(input.is(result)); | |
1911 Register temp = ToRegister(instr->TempAt(0)); | |
1912 Handle<String> class_name = instr->hydrogen()->class_name(); | |
1913 Label done; | |
1914 Label is_true, is_false; | |
1915 | |
1916 EmitClassOfTest(&is_true, &is_false, class_name, input, temp, input); | |
1917 | |
1918 __ j(not_equal, &is_false, Label::kNear); | |
1919 | |
1920 __ bind(&is_true); | |
1921 __ mov(result, factory()->true_value()); | |
1922 __ jmp(&done, Label::kNear); | |
1923 | |
1924 __ bind(&is_false); | |
1925 __ mov(result, factory()->false_value()); | |
1926 __ bind(&done); | |
1927 } | |
1928 | |
1929 | |
1930 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 1732 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
1931 Register input = ToRegister(instr->InputAt(0)); | 1733 Register input = ToRegister(instr->InputAt(0)); |
1932 Register temp = ToRegister(instr->TempAt(0)); | 1734 Register temp = ToRegister(instr->TempAt(0)); |
1933 Register temp2 = ToRegister(instr->TempAt(1)); | 1735 Register temp2 = ToRegister(instr->TempAt(1)); |
1934 if (input.is(temp)) { | 1736 if (input.is(temp)) { |
1935 // Swap. | 1737 // Swap. |
1936 Register swapper = temp; | 1738 Register swapper = temp; |
1937 temp = temp2; | 1739 temp = temp2; |
1938 temp2 = swapper; | 1740 temp2 = swapper; |
1939 } | 1741 } |
(...skipping 2242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4182 LOperand* input = instr->InputAt(0); | 3984 LOperand* input = instr->InputAt(0); |
4183 if (input->IsConstantOperand()) { | 3985 if (input->IsConstantOperand()) { |
4184 __ push(ToImmediate(input)); | 3986 __ push(ToImmediate(input)); |
4185 } else { | 3987 } else { |
4186 __ push(ToOperand(input)); | 3988 __ push(ToOperand(input)); |
4187 } | 3989 } |
4188 CallRuntime(Runtime::kTypeof, 1, instr, RESTORE_CONTEXT); | 3990 CallRuntime(Runtime::kTypeof, 1, instr, RESTORE_CONTEXT); |
4189 } | 3991 } |
4190 | 3992 |
4191 | 3993 |
4192 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { | |
4193 Register input = ToRegister(instr->InputAt(0)); | |
4194 Register result = ToRegister(instr->result()); | |
4195 Label true_label; | |
4196 Label false_label; | |
4197 Label done; | |
4198 | |
4199 Condition final_branch_condition = EmitTypeofIs(&true_label, | |
4200 &false_label, | |
4201 input, | |
4202 instr->type_literal()); | |
4203 __ j(final_branch_condition, &true_label, Label::kNear); | |
4204 __ bind(&false_label); | |
4205 __ mov(result, factory()->false_value()); | |
4206 __ jmp(&done, Label::kNear); | |
4207 | |
4208 __ bind(&true_label); | |
4209 __ mov(result, factory()->true_value()); | |
4210 | |
4211 __ bind(&done); | |
4212 } | |
4213 | |
4214 | |
4215 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 3994 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
4216 Register input = ToRegister(instr->InputAt(0)); | 3995 Register input = ToRegister(instr->InputAt(0)); |
4217 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 3996 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
4218 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 3997 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
4219 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 3998 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
4220 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 3999 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
4221 | 4000 |
4222 Condition final_branch_condition = EmitTypeofIs(true_label, | 4001 Condition final_branch_condition = EmitTypeofIs(true_label, |
4223 false_label, | 4002 false_label, |
4224 input, | 4003 input, |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4285 } else { | 4064 } else { |
4286 final_branch_condition = not_equal; | 4065 final_branch_condition = not_equal; |
4287 __ jmp(false_label); | 4066 __ jmp(false_label); |
4288 // A dead branch instruction will be generated after this point. | 4067 // A dead branch instruction will be generated after this point. |
4289 } | 4068 } |
4290 | 4069 |
4291 return final_branch_condition; | 4070 return final_branch_condition; |
4292 } | 4071 } |
4293 | 4072 |
4294 | 4073 |
4295 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) { | |
4296 Register result = ToRegister(instr->result()); | |
4297 Label true_label; | |
4298 Label done; | |
4299 | |
4300 EmitIsConstructCall(result); | |
4301 __ j(equal, &true_label, Label::kNear); | |
4302 | |
4303 __ mov(result, factory()->false_value()); | |
4304 __ jmp(&done, Label::kNear); | |
4305 | |
4306 __ bind(&true_label); | |
4307 __ mov(result, factory()->true_value()); | |
4308 | |
4309 __ bind(&done); | |
4310 } | |
4311 | |
4312 | |
4313 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 4074 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
4314 Register temp = ToRegister(instr->TempAt(0)); | 4075 Register temp = ToRegister(instr->TempAt(0)); |
4315 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 4076 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
4316 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 4077 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
4317 | 4078 |
4318 EmitIsConstructCall(temp); | 4079 EmitIsConstructCall(temp); |
4319 EmitBranch(true_block, false_block, equal); | 4080 EmitBranch(true_block, false_block, equal); |
4320 } | 4081 } |
4321 | 4082 |
4322 | 4083 |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4461 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 4222 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
4462 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); | 4223 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); |
4463 } | 4224 } |
4464 | 4225 |
4465 | 4226 |
4466 #undef __ | 4227 #undef __ |
4467 | 4228 |
4468 } } // namespace v8::internal | 4229 } } // namespace v8::internal |
4469 | 4230 |
4470 #endif // V8_TARGET_ARCH_IA32 | 4231 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |