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