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