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 1345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1356 __ jmp(chunk_->GetAssemblyLabel(right_block)); | 1356 __ jmp(chunk_->GetAssemblyLabel(right_block)); |
1357 } | 1357 } |
1358 } | 1358 } |
1359 } | 1359 } |
1360 | 1360 |
1361 | 1361 |
1362 void LCodeGen::DoBranch(LBranch* instr) { | 1362 void LCodeGen::DoBranch(LBranch* instr) { |
1363 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1363 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1364 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1364 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1365 | 1365 |
1366 Representation r = instr->hydrogen()->representation(); | 1366 Representation r = instr->hydrogen()->value()->representation(); |
1367 if (r.IsInteger32()) { | 1367 if (r.IsInteger32()) { |
1368 Register reg = ToRegister(instr->InputAt(0)); | 1368 Register reg = ToRegister(instr->InputAt(0)); |
1369 __ testl(reg, reg); | 1369 __ testl(reg, reg); |
1370 EmitBranch(true_block, false_block, not_zero); | 1370 EmitBranch(true_block, false_block, not_zero); |
1371 } else if (r.IsDouble()) { | 1371 } else if (r.IsDouble()) { |
1372 XMMRegister reg = ToDoubleRegister(instr->InputAt(0)); | 1372 XMMRegister reg = ToDoubleRegister(instr->InputAt(0)); |
1373 __ xorps(xmm0, xmm0); | 1373 __ xorps(xmm0, xmm0); |
1374 __ ucomisd(reg, xmm0); | 1374 __ ucomisd(reg, xmm0); |
1375 EmitBranch(true_block, false_block, not_equal); | 1375 EmitBranch(true_block, false_block, not_equal); |
1376 } else { | 1376 } else { |
1377 ASSERT(r.IsTagged()); | 1377 ASSERT(r.IsTagged()); |
1378 Register reg = ToRegister(instr->InputAt(0)); | 1378 Register reg = ToRegister(instr->InputAt(0)); |
1379 HType type = instr->hydrogen()->type(); | 1379 HType type = instr->hydrogen()->value()->type(); |
1380 if (type.IsBoolean()) { | 1380 if (type.IsBoolean()) { |
1381 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 1381 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
1382 EmitBranch(true_block, false_block, equal); | 1382 EmitBranch(true_block, false_block, equal); |
1383 } else if (type.IsSmi()) { | 1383 } else if (type.IsSmi()) { |
1384 __ SmiCompare(reg, Smi::FromInt(0)); | 1384 __ SmiCompare(reg, Smi::FromInt(0)); |
1385 EmitBranch(true_block, false_block, not_equal); | 1385 EmitBranch(true_block, false_block, not_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 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1476 __ cmpl(ToOperand(left), Immediate(value)); | 1476 __ cmpl(ToOperand(left), Immediate(value)); |
1477 } | 1477 } |
1478 } else if (right->IsRegister()) { | 1478 } else if (right->IsRegister()) { |
1479 __ cmpl(ToRegister(left), ToRegister(right)); | 1479 __ cmpl(ToRegister(left), ToRegister(right)); |
1480 } else { | 1480 } else { |
1481 __ cmpl(ToRegister(left), ToOperand(right)); | 1481 __ cmpl(ToRegister(left), ToOperand(right)); |
1482 } | 1482 } |
1483 } | 1483 } |
1484 | 1484 |
1485 | 1485 |
1486 void LCodeGen::DoCmpID(LCmpID* instr) { | |
1487 LOperand* left = instr->InputAt(0); | |
1488 LOperand* right = instr->InputAt(1); | |
1489 LOperand* result = instr->result(); | |
1490 | |
1491 Label unordered; | |
1492 if (instr->is_double()) { | |
1493 // Don't base result on EFLAGS when a NaN is involved. Instead | |
1494 // jump to the unordered case, which produces a false value. | |
1495 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); | |
1496 __ j(parity_even, &unordered, Label::kNear); | |
1497 } else { | |
1498 EmitCmpI(left, right); | |
1499 } | |
1500 | |
1501 Label done; | |
1502 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | |
1503 __ LoadRoot(ToRegister(result), Heap::kTrueValueRootIndex); | |
1504 __ j(cc, &done, Label::kNear); | |
1505 | |
1506 __ bind(&unordered); | |
1507 __ LoadRoot(ToRegister(result), Heap::kFalseValueRootIndex); | |
1508 __ bind(&done); | |
1509 } | |
1510 | |
1511 | |
1512 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 1486 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
1513 LOperand* left = instr->InputAt(0); | 1487 LOperand* left = instr->InputAt(0); |
1514 LOperand* right = instr->InputAt(1); | 1488 LOperand* right = instr->InputAt(1); |
1515 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1489 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1516 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1490 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1517 | 1491 |
1518 if (instr->is_double()) { | 1492 if (instr->is_double()) { |
1519 // Don't base result on EFLAGS when a NaN is involved. Instead | 1493 // Don't base result on EFLAGS when a NaN is involved. Instead |
1520 // jump to the false block. | 1494 // jump to the false block. |
1521 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); | 1495 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); |
1522 __ j(parity_even, chunk_->GetAssemblyLabel(false_block)); | 1496 __ j(parity_even, chunk_->GetAssemblyLabel(false_block)); |
1523 } else { | 1497 } else { |
1524 EmitCmpI(left, right); | 1498 EmitCmpI(left, right); |
1525 } | 1499 } |
1526 | 1500 |
1527 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | 1501 Condition cc = TokenToCondition(instr->op(), instr->is_double()); |
1528 EmitBranch(true_block, false_block, cc); | 1502 EmitBranch(true_block, false_block, cc); |
1529 } | 1503 } |
1530 | 1504 |
1531 | 1505 |
1532 void LCodeGen::DoCmpObjectEq(LCmpObjectEq* instr) { | |
1533 Register left = ToRegister(instr->InputAt(0)); | |
1534 Register right = ToRegister(instr->InputAt(1)); | |
1535 Register result = ToRegister(instr->result()); | |
1536 | |
1537 Label different, done; | |
1538 __ cmpq(left, right); | |
1539 __ j(not_equal, &different, Label::kNear); | |
1540 __ LoadRoot(result, Heap::kTrueValueRootIndex); | |
1541 __ jmp(&done, Label::kNear); | |
1542 __ bind(&different); | |
1543 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
1544 __ bind(&done); | |
1545 } | |
1546 | |
1547 | |
1548 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { | 1506 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { |
1549 Register left = ToRegister(instr->InputAt(0)); | 1507 Register left = ToRegister(instr->InputAt(0)); |
1550 Register right = ToRegister(instr->InputAt(1)); | 1508 Register right = ToRegister(instr->InputAt(1)); |
1551 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1509 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1552 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1510 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1553 | 1511 |
1554 __ cmpq(left, right); | 1512 __ cmpq(left, right); |
1555 EmitBranch(true_block, false_block, equal); | 1513 EmitBranch(true_block, false_block, equal); |
1556 } | 1514 } |
1557 | 1515 |
1558 | 1516 |
1559 void LCodeGen::DoCmpConstantEq(LCmpConstantEq* instr) { | |
1560 Register left = ToRegister(instr->InputAt(0)); | |
1561 Register result = ToRegister(instr->result()); | |
1562 | |
1563 Label done; | |
1564 __ cmpq(left, Immediate(instr->hydrogen()->right())); | |
1565 __ LoadRoot(result, Heap::kTrueValueRootIndex); | |
1566 __ j(equal, &done, Label::kNear); | |
1567 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
1568 __ bind(&done); | |
1569 } | |
1570 | |
1571 | |
1572 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { | 1517 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { |
1573 Register left = ToRegister(instr->InputAt(0)); | 1518 Register left = ToRegister(instr->InputAt(0)); |
1574 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1519 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1575 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1520 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1576 | 1521 |
1577 __ cmpq(left, Immediate(instr->hydrogen()->right())); | 1522 __ cmpq(left, Immediate(instr->hydrogen()->right())); |
1578 EmitBranch(true_block, false_block, equal); | 1523 EmitBranch(true_block, false_block, equal); |
1579 } | 1524 } |
1580 | 1525 |
1581 | 1526 |
1582 void LCodeGen::DoIsNull(LIsNull* instr) { | |
1583 Register reg = ToRegister(instr->InputAt(0)); | |
1584 Register result = ToRegister(instr->result()); | |
1585 | |
1586 // If the expression is known to be a smi, then it's | |
1587 // definitely not null. Materialize false. | |
1588 // Consider adding other type and representation tests too. | |
1589 if (instr->hydrogen()->value()->type().IsSmi()) { | |
1590 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
1591 return; | |
1592 } | |
1593 | |
1594 __ CompareRoot(reg, Heap::kNullValueRootIndex); | |
1595 if (instr->is_strict()) { | |
1596 ASSERT(Heap::kTrueValueRootIndex >= 0); | |
1597 __ movl(result, Immediate(Heap::kTrueValueRootIndex)); | |
1598 Label load; | |
1599 __ j(equal, &load, Label::kNear); | |
1600 __ Set(result, Heap::kFalseValueRootIndex); | |
1601 __ bind(&load); | |
1602 __ LoadRootIndexed(result, result, 0); | |
1603 } else { | |
1604 Label false_value, true_value, done; | |
1605 __ j(equal, &true_value, Label::kNear); | |
1606 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); | |
1607 __ j(equal, &true_value, Label::kNear); | |
1608 __ JumpIfSmi(reg, &false_value, Label::kNear); | |
1609 // Check for undetectable objects by looking in the bit field in | |
1610 // the map. The object has already been smi checked. | |
1611 Register scratch = result; | |
1612 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | |
1613 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), | |
1614 Immediate(1 << Map::kIsUndetectable)); | |
1615 __ j(not_zero, &true_value, Label::kNear); | |
1616 __ bind(&false_value); | |
1617 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
1618 __ jmp(&done, Label::kNear); | |
1619 __ bind(&true_value); | |
1620 __ LoadRoot(result, Heap::kTrueValueRootIndex); | |
1621 __ bind(&done); | |
1622 } | |
1623 } | |
1624 | |
1625 | |
1626 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { | 1527 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { |
1627 Register reg = ToRegister(instr->InputAt(0)); | 1528 Register reg = ToRegister(instr->InputAt(0)); |
1628 | 1529 |
1629 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1530 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1630 | 1531 |
1631 if (instr->hydrogen()->representation().IsSpecialization() || | 1532 if (instr->hydrogen()->representation().IsSpecialization() || |
1632 instr->hydrogen()->type().IsSmi()) { | 1533 instr->hydrogen()->type().IsSmi()) { |
1633 // If the expression is known to untagged or smi, then it's definitely | 1534 // If the expression is known to untagged or smi, then it's definitely |
1634 // not null, and it can't be a an undetectable object. | 1535 // not null, and it can't be a an undetectable object. |
1635 // Jump directly to the false block. | 1536 // Jump directly to the false block. |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1678 | 1579 |
1679 __ movzxbl(kScratchRegister, | 1580 __ movzxbl(kScratchRegister, |
1680 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); | 1581 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); |
1681 __ cmpb(kScratchRegister, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 1582 __ cmpb(kScratchRegister, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
1682 __ j(below, is_not_object); | 1583 __ j(below, is_not_object); |
1683 __ cmpb(kScratchRegister, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 1584 __ cmpb(kScratchRegister, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
1684 return below_equal; | 1585 return below_equal; |
1685 } | 1586 } |
1686 | 1587 |
1687 | 1588 |
1688 void LCodeGen::DoIsObject(LIsObject* instr) { | |
1689 Register reg = ToRegister(instr->InputAt(0)); | |
1690 Register result = ToRegister(instr->result()); | |
1691 Label is_false, is_true, done; | |
1692 | |
1693 Condition true_cond = EmitIsObject(reg, &is_false, &is_true); | |
1694 __ j(true_cond, &is_true); | |
1695 | |
1696 __ bind(&is_false); | |
1697 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
1698 __ jmp(&done); | |
1699 | |
1700 __ bind(&is_true); | |
1701 __ LoadRoot(result, Heap::kTrueValueRootIndex); | |
1702 | |
1703 __ bind(&done); | |
1704 } | |
1705 | |
1706 | |
1707 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 1589 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
1708 Register reg = ToRegister(instr->InputAt(0)); | 1590 Register reg = ToRegister(instr->InputAt(0)); |
1709 | 1591 |
1710 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1592 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1711 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1593 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1712 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1594 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1713 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1595 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1714 | 1596 |
1715 Condition true_cond = EmitIsObject(reg, false_label, true_label); | 1597 Condition true_cond = EmitIsObject(reg, false_label, true_label); |
1716 | 1598 |
1717 EmitBranch(true_block, false_block, true_cond); | 1599 EmitBranch(true_block, false_block, true_cond); |
1718 } | 1600 } |
1719 | 1601 |
1720 | 1602 |
1721 void LCodeGen::DoIsSmi(LIsSmi* instr) { | |
1722 LOperand* input_operand = instr->InputAt(0); | |
1723 Register result = ToRegister(instr->result()); | |
1724 if (input_operand->IsRegister()) { | |
1725 Register input = ToRegister(input_operand); | |
1726 __ CheckSmiToIndicator(result, input); | |
1727 } else { | |
1728 Operand input = ToOperand(instr->InputAt(0)); | |
1729 __ CheckSmiToIndicator(result, input); | |
1730 } | |
1731 // result is zero if input is a smi, and one otherwise. | |
1732 ASSERT(Heap::kFalseValueRootIndex == Heap::kTrueValueRootIndex + 1); | |
1733 __ LoadRootIndexed(result, result, Heap::kTrueValueRootIndex); | |
1734 } | |
1735 | |
1736 | |
1737 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 1603 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
1738 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1604 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1739 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1605 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1740 | 1606 |
1741 Condition is_smi; | 1607 Condition is_smi; |
1742 if (instr->InputAt(0)->IsRegister()) { | 1608 if (instr->InputAt(0)->IsRegister()) { |
1743 Register input = ToRegister(instr->InputAt(0)); | 1609 Register input = ToRegister(instr->InputAt(0)); |
1744 is_smi = masm()->CheckSmi(input); | 1610 is_smi = masm()->CheckSmi(input); |
1745 } else { | 1611 } else { |
1746 Operand input = ToOperand(instr->InputAt(0)); | 1612 Operand input = ToOperand(instr->InputAt(0)); |
1747 is_smi = masm()->CheckSmi(input); | 1613 is_smi = masm()->CheckSmi(input); |
1748 } | 1614 } |
1749 EmitBranch(true_block, false_block, is_smi); | 1615 EmitBranch(true_block, false_block, is_smi); |
1750 } | 1616 } |
1751 | 1617 |
1752 | 1618 |
1753 void LCodeGen::DoIsUndetectable(LIsUndetectable* instr) { | |
1754 Register input = ToRegister(instr->InputAt(0)); | |
1755 Register result = ToRegister(instr->result()); | |
1756 | |
1757 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | |
1758 Label false_label, done; | |
1759 __ JumpIfSmi(input, &false_label); | |
1760 __ movq(result, FieldOperand(input, HeapObject::kMapOffset)); | |
1761 __ testb(FieldOperand(result, Map::kBitFieldOffset), | |
1762 Immediate(1 << Map::kIsUndetectable)); | |
1763 __ j(zero, &false_label); | |
1764 __ LoadRoot(result, Heap::kTrueValueRootIndex); | |
1765 __ jmp(&done); | |
1766 __ bind(&false_label); | |
1767 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
1768 __ bind(&done); | |
1769 } | |
1770 | |
1771 | |
1772 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { | 1619 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { |
1773 Register input = ToRegister(instr->InputAt(0)); | 1620 Register input = ToRegister(instr->InputAt(0)); |
1774 Register temp = ToRegister(instr->TempAt(0)); | 1621 Register temp = ToRegister(instr->TempAt(0)); |
1775 | 1622 |
1776 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1623 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1777 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1624 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1778 | 1625 |
1779 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); | 1626 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); |
1780 __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); | 1627 __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); |
1781 __ testb(FieldOperand(temp, Map::kBitFieldOffset), | 1628 __ testb(FieldOperand(temp, Map::kBitFieldOffset), |
1782 Immediate(1 << Map::kIsUndetectable)); | 1629 Immediate(1 << Map::kIsUndetectable)); |
1783 EmitBranch(true_block, false_block, not_zero); | 1630 EmitBranch(true_block, false_block, not_zero); |
1784 } | 1631 } |
1785 | 1632 |
1786 | 1633 |
1787 static InstanceType TestType(HHasInstanceType* instr) { | 1634 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { |
1788 InstanceType from = instr->from(); | 1635 InstanceType from = instr->from(); |
1789 InstanceType to = instr->to(); | 1636 InstanceType to = instr->to(); |
1790 if (from == FIRST_TYPE) return to; | 1637 if (from == FIRST_TYPE) return to; |
1791 ASSERT(from == to || to == LAST_TYPE); | 1638 ASSERT(from == to || to == LAST_TYPE); |
1792 return from; | 1639 return from; |
1793 } | 1640 } |
1794 | 1641 |
1795 | 1642 |
1796 static Condition BranchCondition(HHasInstanceType* instr) { | 1643 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { |
1797 InstanceType from = instr->from(); | 1644 InstanceType from = instr->from(); |
1798 InstanceType to = instr->to(); | 1645 InstanceType to = instr->to(); |
1799 if (from == to) return equal; | 1646 if (from == to) return equal; |
1800 if (to == LAST_TYPE) return above_equal; | 1647 if (to == LAST_TYPE) return above_equal; |
1801 if (from == FIRST_TYPE) return below_equal; | 1648 if (from == FIRST_TYPE) return below_equal; |
1802 UNREACHABLE(); | 1649 UNREACHABLE(); |
1803 return equal; | 1650 return equal; |
1804 } | 1651 } |
1805 | 1652 |
1806 | 1653 |
1807 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { | |
1808 Register input = ToRegister(instr->InputAt(0)); | |
1809 Register result = ToRegister(instr->result()); | |
1810 | |
1811 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | |
1812 __ testl(input, Immediate(kSmiTagMask)); | |
1813 Label done, is_false; | |
1814 __ j(zero, &is_false); | |
1815 __ CmpObjectType(input, TestType(instr->hydrogen()), result); | |
1816 __ j(NegateCondition(BranchCondition(instr->hydrogen())), | |
1817 &is_false, Label::kNear); | |
1818 __ LoadRoot(result, Heap::kTrueValueRootIndex); | |
1819 __ jmp(&done, Label::kNear); | |
1820 __ bind(&is_false); | |
1821 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
1822 __ bind(&done); | |
1823 } | |
1824 | |
1825 | |
1826 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 1654 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
1827 Register input = ToRegister(instr->InputAt(0)); | 1655 Register input = ToRegister(instr->InputAt(0)); |
1828 | 1656 |
1829 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1657 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1830 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1658 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1831 | 1659 |
1832 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1660 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1833 | 1661 |
1834 __ JumpIfSmi(input, false_label); | 1662 __ JumpIfSmi(input, false_label); |
1835 | 1663 |
1836 __ CmpObjectType(input, TestType(instr->hydrogen()), kScratchRegister); | 1664 __ CmpObjectType(input, TestType(instr->hydrogen()), kScratchRegister); |
1837 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); | 1665 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); |
1838 } | 1666 } |
1839 | 1667 |
1840 | 1668 |
1841 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { | 1669 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { |
1842 Register input = ToRegister(instr->InputAt(0)); | 1670 Register input = ToRegister(instr->InputAt(0)); |
1843 Register result = ToRegister(instr->result()); | 1671 Register result = ToRegister(instr->result()); |
1844 | 1672 |
1845 if (FLAG_debug_code) { | 1673 if (FLAG_debug_code) { |
1846 __ AbortIfNotString(input); | 1674 __ AbortIfNotString(input); |
1847 } | 1675 } |
1848 | 1676 |
1849 __ movl(result, FieldOperand(input, String::kHashFieldOffset)); | 1677 __ movl(result, FieldOperand(input, String::kHashFieldOffset)); |
1850 ASSERT(String::kHashShift >= kSmiTagSize); | 1678 ASSERT(String::kHashShift >= kSmiTagSize); |
1851 __ IndexFromHash(result, result); | 1679 __ IndexFromHash(result, result); |
1852 } | 1680 } |
1853 | 1681 |
1854 | 1682 |
1855 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { | |
1856 Register input = ToRegister(instr->InputAt(0)); | |
1857 Register result = ToRegister(instr->result()); | |
1858 | |
1859 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | |
1860 __ LoadRoot(result, Heap::kTrueValueRootIndex); | |
1861 __ testl(FieldOperand(input, String::kHashFieldOffset), | |
1862 Immediate(String::kContainsCachedArrayIndexMask)); | |
1863 Label done; | |
1864 __ j(zero, &done, Label::kNear); | |
1865 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
1866 __ bind(&done); | |
1867 } | |
1868 | |
1869 | |
1870 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 1683 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
1871 LHasCachedArrayIndexAndBranch* instr) { | 1684 LHasCachedArrayIndexAndBranch* instr) { |
1872 Register input = ToRegister(instr->InputAt(0)); | 1685 Register input = ToRegister(instr->InputAt(0)); |
1873 | 1686 |
1874 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1687 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1875 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1688 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1876 | 1689 |
1877 __ testl(FieldOperand(input, String::kHashFieldOffset), | 1690 __ testl(FieldOperand(input, String::kHashFieldOffset), |
1878 Immediate(String::kContainsCachedArrayIndexMask)); | 1691 Immediate(String::kContainsCachedArrayIndexMask)); |
1879 EmitBranch(true_block, false_block, equal); | 1692 EmitBranch(true_block, false_block, equal); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1928 // booted. This routine isn't expected to work for random API-created | 1741 // booted. This routine isn't expected to work for random API-created |
1929 // classes and it doesn't have to because you can't access it with natives | 1742 // classes and it doesn't have to because you can't access it with natives |
1930 // syntax. Since both sides are symbols it is sufficient to use an identity | 1743 // syntax. Since both sides are symbols it is sufficient to use an identity |
1931 // comparison. | 1744 // comparison. |
1932 ASSERT(class_name->IsSymbol()); | 1745 ASSERT(class_name->IsSymbol()); |
1933 __ Cmp(temp, class_name); | 1746 __ Cmp(temp, class_name); |
1934 // End with the answer in the z flag. | 1747 // End with the answer in the z flag. |
1935 } | 1748 } |
1936 | 1749 |
1937 | 1750 |
1938 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { | |
1939 Register input = ToRegister(instr->InputAt(0)); | |
1940 Register result = ToRegister(instr->result()); | |
1941 ASSERT(input.is(result)); | |
1942 Register temp = ToRegister(instr->TempAt(0)); | |
1943 Handle<String> class_name = instr->hydrogen()->class_name(); | |
1944 Label done; | |
1945 Label is_true, is_false; | |
1946 | |
1947 EmitClassOfTest(&is_true, &is_false, class_name, input, temp); | |
1948 | |
1949 __ j(not_equal, &is_false); | |
1950 | |
1951 __ bind(&is_true); | |
1952 __ LoadRoot(result, Heap::kTrueValueRootIndex); | |
1953 __ jmp(&done, Label::kNear); | |
1954 | |
1955 __ bind(&is_false); | |
1956 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
1957 __ bind(&done); | |
1958 } | |
1959 | |
1960 | |
1961 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 1751 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
1962 Register input = ToRegister(instr->InputAt(0)); | 1752 Register input = ToRegister(instr->InputAt(0)); |
1963 Register temp = ToRegister(instr->TempAt(0)); | 1753 Register temp = ToRegister(instr->TempAt(0)); |
1964 Handle<String> class_name = instr->hydrogen()->class_name(); | 1754 Handle<String> class_name = instr->hydrogen()->class_name(); |
1965 | 1755 |
1966 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1756 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1967 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1757 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1968 | 1758 |
1969 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1759 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1970 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1760 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
(...skipping 2047 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4018 } | 3808 } |
4019 | 3809 |
4020 | 3810 |
4021 void LCodeGen::DoTypeof(LTypeof* instr) { | 3811 void LCodeGen::DoTypeof(LTypeof* instr) { |
4022 LOperand* input = instr->InputAt(0); | 3812 LOperand* input = instr->InputAt(0); |
4023 EmitPushTaggedOperand(input); | 3813 EmitPushTaggedOperand(input); |
4024 CallRuntime(Runtime::kTypeof, 1, instr); | 3814 CallRuntime(Runtime::kTypeof, 1, instr); |
4025 } | 3815 } |
4026 | 3816 |
4027 | 3817 |
4028 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { | |
4029 Register input = ToRegister(instr->InputAt(0)); | |
4030 Register result = ToRegister(instr->result()); | |
4031 Label true_label; | |
4032 Label false_label; | |
4033 Label done; | |
4034 | |
4035 Condition final_branch_condition = EmitTypeofIs(&true_label, | |
4036 &false_label, | |
4037 input, | |
4038 instr->type_literal()); | |
4039 __ j(final_branch_condition, &true_label); | |
4040 __ bind(&false_label); | |
4041 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
4042 __ jmp(&done, Label::kNear); | |
4043 | |
4044 __ bind(&true_label); | |
4045 __ LoadRoot(result, Heap::kTrueValueRootIndex); | |
4046 | |
4047 __ bind(&done); | |
4048 } | |
4049 | |
4050 | |
4051 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { | 3818 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { |
4052 ASSERT(!operand->IsDoubleRegister()); | 3819 ASSERT(!operand->IsDoubleRegister()); |
4053 if (operand->IsConstantOperand()) { | 3820 if (operand->IsConstantOperand()) { |
4054 __ Push(ToHandle(LConstantOperand::cast(operand))); | 3821 __ Push(ToHandle(LConstantOperand::cast(operand))); |
4055 } else if (operand->IsRegister()) { | 3822 } else if (operand->IsRegister()) { |
4056 __ push(ToRegister(operand)); | 3823 __ push(ToRegister(operand)); |
4057 } else { | 3824 } else { |
4058 __ push(ToOperand(operand)); | 3825 __ push(ToOperand(operand)); |
4059 } | 3826 } |
4060 } | 3827 } |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4132 | 3899 |
4133 } else { | 3900 } else { |
4134 final_branch_condition = never; | 3901 final_branch_condition = never; |
4135 __ jmp(false_label); | 3902 __ jmp(false_label); |
4136 } | 3903 } |
4137 | 3904 |
4138 return final_branch_condition; | 3905 return final_branch_condition; |
4139 } | 3906 } |
4140 | 3907 |
4141 | 3908 |
4142 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) { | |
4143 Register result = ToRegister(instr->result()); | |
4144 Label true_label; | |
4145 Label done; | |
4146 | |
4147 EmitIsConstructCall(result); | |
4148 __ j(equal, &true_label, Label::kNear); | |
4149 | |
4150 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
4151 __ jmp(&done, Label::kNear); | |
4152 | |
4153 __ bind(&true_label); | |
4154 __ LoadRoot(result, Heap::kTrueValueRootIndex); | |
4155 | |
4156 | |
4157 __ bind(&done); | |
4158 } | |
4159 | |
4160 | |
4161 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 3909 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
4162 Register temp = ToRegister(instr->TempAt(0)); | 3910 Register temp = ToRegister(instr->TempAt(0)); |
4163 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 3911 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
4164 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 3912 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
4165 | 3913 |
4166 EmitIsConstructCall(temp); | 3914 EmitIsConstructCall(temp); |
4167 EmitBranch(true_block, false_block, equal); | 3915 EmitBranch(true_block, false_block, equal); |
4168 } | 3916 } |
4169 | 3917 |
4170 | 3918 |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4289 RegisterEnvironmentForDeoptimization(environment); | 4037 RegisterEnvironmentForDeoptimization(environment); |
4290 ASSERT(osr_pc_offset_ == -1); | 4038 ASSERT(osr_pc_offset_ == -1); |
4291 osr_pc_offset_ = masm()->pc_offset(); | 4039 osr_pc_offset_ = masm()->pc_offset(); |
4292 } | 4040 } |
4293 | 4041 |
4294 #undef __ | 4042 #undef __ |
4295 | 4043 |
4296 } } // namespace v8::internal | 4044 } } // namespace v8::internal |
4297 | 4045 |
4298 #endif // V8_TARGET_ARCH_X64 | 4046 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |