| 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 |