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 814 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
825 __ test(edx, Operand(edx)); | 825 __ test(edx, Operand(edx)); |
826 DeoptimizeIf(not_zero, instr->environment()); | 826 DeoptimizeIf(not_zero, instr->environment()); |
827 } | 827 } |
828 | 828 |
829 | 829 |
830 void LCodeGen::DoMulI(LMulI* instr) { | 830 void LCodeGen::DoMulI(LMulI* instr) { |
831 Register left = ToRegister(instr->left()); | 831 Register left = ToRegister(instr->left()); |
832 LOperand* right = instr->right(); | 832 LOperand* right = instr->right(); |
833 | 833 |
834 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 834 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
835 __ mov(ToRegister(instr->temp()), left); | 835 __ mov(ToRegister(instr->TempAt(0)), left); |
836 } | 836 } |
837 | 837 |
838 if (right->IsConstantOperand()) { | 838 if (right->IsConstantOperand()) { |
839 __ imul(left, left, ToInteger32(LConstantOperand::cast(right))); | 839 __ imul(left, left, ToInteger32(LConstantOperand::cast(right))); |
840 } else { | 840 } else { |
841 __ imul(left, ToOperand(right)); | 841 __ imul(left, ToOperand(right)); |
842 } | 842 } |
843 | 843 |
844 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 844 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
845 DeoptimizeIf(overflow, instr->environment()); | 845 DeoptimizeIf(overflow, instr->environment()); |
846 } | 846 } |
847 | 847 |
848 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 848 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
849 // Bail out if the result is supposed to be negative zero. | 849 // Bail out if the result is supposed to be negative zero. |
850 NearLabel done; | 850 NearLabel done; |
851 __ test(left, Operand(left)); | 851 __ test(left, Operand(left)); |
852 __ j(not_zero, &done); | 852 __ j(not_zero, &done); |
853 if (right->IsConstantOperand()) { | 853 if (right->IsConstantOperand()) { |
854 if (ToInteger32(LConstantOperand::cast(right)) < 0) { | 854 if (ToInteger32(LConstantOperand::cast(right)) < 0) { |
855 DeoptimizeIf(no_condition, instr->environment()); | 855 DeoptimizeIf(no_condition, instr->environment()); |
856 } | 856 } |
857 } else { | 857 } else { |
858 // Test the non-zero operand for negative sign. | 858 // Test the non-zero operand for negative sign. |
859 __ or_(ToRegister(instr->temp()), ToOperand(right)); | 859 __ or_(ToRegister(instr->TempAt(0)), ToOperand(right)); |
860 DeoptimizeIf(sign, instr->environment()); | 860 DeoptimizeIf(sign, instr->environment()); |
861 } | 861 } |
862 __ bind(&done); | 862 __ bind(&done); |
863 } | 863 } |
864 } | 864 } |
865 | 865 |
866 | 866 |
867 void LCodeGen::DoBitI(LBitI* instr) { | 867 void LCodeGen::DoBitI(LBitI* instr) { |
868 LOperand* left = instr->left(); | 868 LOperand* left = instr->left(); |
869 LOperand* right = instr->right(); | 869 LOperand* right = instr->right(); |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1026 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { | 1026 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { |
1027 Register result = ToRegister(instr->result()); | 1027 Register result = ToRegister(instr->result()); |
1028 Register array = ToRegister(instr->input()); | 1028 Register array = ToRegister(instr->input()); |
1029 __ mov(result, FieldOperand(array, FixedArray::kLengthOffset)); | 1029 __ mov(result, FieldOperand(array, FixedArray::kLengthOffset)); |
1030 } | 1030 } |
1031 | 1031 |
1032 | 1032 |
1033 void LCodeGen::DoValueOf(LValueOf* instr) { | 1033 void LCodeGen::DoValueOf(LValueOf* instr) { |
1034 Register input = ToRegister(instr->input()); | 1034 Register input = ToRegister(instr->input()); |
1035 Register result = ToRegister(instr->result()); | 1035 Register result = ToRegister(instr->result()); |
1036 Register map = ToRegister(instr->temporary()); | 1036 Register map = ToRegister(instr->TempAt(0)); |
1037 ASSERT(input.is(result)); | 1037 ASSERT(input.is(result)); |
1038 NearLabel done; | 1038 NearLabel done; |
1039 // If the object is a smi return the object. | 1039 // If the object is a smi return the object. |
1040 __ test(input, Immediate(kSmiTagMask)); | 1040 __ test(input, Immediate(kSmiTagMask)); |
1041 __ j(zero, &done); | 1041 __ j(zero, &done); |
1042 | 1042 |
1043 // If the object is not a value type, return the object. | 1043 // If the object is not a value type, return the object. |
1044 __ CmpObjectType(input, JS_VALUE_TYPE, map); | 1044 __ CmpObjectType(input, JS_VALUE_TYPE, map); |
1045 __ j(not_equal, &done); | 1045 __ j(not_equal, &done); |
1046 __ mov(result, FieldOperand(input, JSValue::kValueOffset)); | 1046 __ mov(result, FieldOperand(input, JSValue::kValueOffset)); |
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1428 } else { | 1428 } else { |
1429 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1429 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1430 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1430 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1431 __ j(equal, true_label); | 1431 __ j(equal, true_label); |
1432 __ cmp(reg, Factory::undefined_value()); | 1432 __ cmp(reg, Factory::undefined_value()); |
1433 __ j(equal, true_label); | 1433 __ j(equal, true_label); |
1434 __ test(reg, Immediate(kSmiTagMask)); | 1434 __ test(reg, Immediate(kSmiTagMask)); |
1435 __ j(zero, false_label); | 1435 __ j(zero, false_label); |
1436 // Check for undetectable objects by looking in the bit field in | 1436 // Check for undetectable objects by looking in the bit field in |
1437 // the map. The object has already been smi checked. | 1437 // the map. The object has already been smi checked. |
1438 Register scratch = ToRegister(instr->temp()); | 1438 Register scratch = ToRegister(instr->TempAt(0)); |
1439 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 1439 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
1440 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); | 1440 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); |
1441 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); | 1441 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); |
1442 EmitBranch(true_block, false_block, not_zero); | 1442 EmitBranch(true_block, false_block, not_zero); |
1443 } | 1443 } |
1444 } | 1444 } |
1445 | 1445 |
1446 | 1446 |
1447 Condition LCodeGen::EmitIsObject(Register input, | 1447 Condition LCodeGen::EmitIsObject(Register input, |
1448 Register temp1, | 1448 Register temp1, |
(...skipping 20 matching lines...) Expand all Loading... |
1469 __ cmp(temp2, FIRST_JS_OBJECT_TYPE); | 1469 __ cmp(temp2, FIRST_JS_OBJECT_TYPE); |
1470 __ j(below, is_not_object); | 1470 __ j(below, is_not_object); |
1471 __ cmp(temp2, LAST_JS_OBJECT_TYPE); | 1471 __ cmp(temp2, LAST_JS_OBJECT_TYPE); |
1472 return below_equal; | 1472 return below_equal; |
1473 } | 1473 } |
1474 | 1474 |
1475 | 1475 |
1476 void LCodeGen::DoIsObject(LIsObject* instr) { | 1476 void LCodeGen::DoIsObject(LIsObject* instr) { |
1477 Register reg = ToRegister(instr->input()); | 1477 Register reg = ToRegister(instr->input()); |
1478 Register result = ToRegister(instr->result()); | 1478 Register result = ToRegister(instr->result()); |
1479 Register temp = ToRegister(instr->temp()); | 1479 Register temp = ToRegister(instr->TempAt(0)); |
1480 Label is_false, is_true, done; | 1480 Label is_false, is_true, done; |
1481 | 1481 |
1482 Condition true_cond = EmitIsObject(reg, result, temp, &is_false, &is_true); | 1482 Condition true_cond = EmitIsObject(reg, result, temp, &is_false, &is_true); |
1483 __ j(true_cond, &is_true); | 1483 __ j(true_cond, &is_true); |
1484 | 1484 |
1485 __ bind(&is_false); | 1485 __ bind(&is_false); |
1486 __ mov(result, Handle<Object>(Heap::false_value())); | 1486 __ mov(result, Handle<Object>(Heap::false_value())); |
1487 __ jmp(&done); | 1487 __ jmp(&done); |
1488 | 1488 |
1489 __ bind(&is_true); | 1489 __ bind(&is_true); |
1490 __ mov(result, Handle<Object>(Heap::true_value())); | 1490 __ mov(result, Handle<Object>(Heap::true_value())); |
1491 | 1491 |
1492 __ bind(&done); | 1492 __ bind(&done); |
1493 } | 1493 } |
1494 | 1494 |
1495 | 1495 |
1496 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 1496 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
1497 Register reg = ToRegister(instr->input()); | 1497 Register reg = ToRegister(instr->input()); |
1498 Register temp = ToRegister(instr->temp()); | 1498 Register temp = ToRegister(instr->TempAt(0)); |
1499 Register temp2 = ToRegister(instr->temp2()); | 1499 Register temp2 = ToRegister(instr->TempAt(1)); |
1500 | 1500 |
1501 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1501 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1502 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1502 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1503 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1503 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1504 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1504 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1505 | 1505 |
1506 Condition true_cond = EmitIsObject(reg, temp, temp2, false_label, true_label); | 1506 Condition true_cond = EmitIsObject(reg, temp, temp2, false_label, true_label); |
1507 | 1507 |
1508 EmitBranch(true_block, false_block, true_cond); | 1508 EmitBranch(true_block, false_block, true_cond); |
1509 } | 1509 } |
(...skipping 17 matching lines...) Expand all Loading... |
1527 Operand input = ToOperand(instr->input()); | 1527 Operand input = ToOperand(instr->input()); |
1528 | 1528 |
1529 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1529 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1530 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1530 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1531 | 1531 |
1532 __ test(input, Immediate(kSmiTagMask)); | 1532 __ test(input, Immediate(kSmiTagMask)); |
1533 EmitBranch(true_block, false_block, zero); | 1533 EmitBranch(true_block, false_block, zero); |
1534 } | 1534 } |
1535 | 1535 |
1536 | 1536 |
1537 InstanceType LHasInstanceType::TestType() { | 1537 static InstanceType TestType(HHasInstanceType* instr) { |
1538 InstanceType from = hydrogen()->from(); | 1538 InstanceType from = instr->from(); |
1539 InstanceType to = hydrogen()->to(); | 1539 InstanceType to = instr->to(); |
1540 if (from == FIRST_TYPE) return to; | 1540 if (from == FIRST_TYPE) return to; |
1541 ASSERT(from == to || to == LAST_TYPE); | 1541 ASSERT(from == to || to == LAST_TYPE); |
1542 return from; | 1542 return from; |
1543 } | 1543 } |
1544 | 1544 |
1545 | 1545 |
1546 | 1546 |
1547 Condition LHasInstanceType::BranchCondition() { | 1547 static Condition BranchCondition(HHasInstanceType* instr) { |
1548 InstanceType from = hydrogen()->from(); | 1548 InstanceType from = instr->from(); |
1549 InstanceType to = hydrogen()->to(); | 1549 InstanceType to = instr->to(); |
1550 if (from == to) return equal; | 1550 if (from == to) return equal; |
1551 if (to == LAST_TYPE) return above_equal; | 1551 if (to == LAST_TYPE) return above_equal; |
1552 if (from == FIRST_TYPE) return below_equal; | 1552 if (from == FIRST_TYPE) return below_equal; |
1553 UNREACHABLE(); | 1553 UNREACHABLE(); |
1554 return equal; | 1554 return equal; |
1555 } | 1555 } |
1556 | 1556 |
1557 | 1557 |
1558 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { | 1558 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { |
1559 Register input = ToRegister(instr->input()); | 1559 Register input = ToRegister(instr->input()); |
1560 Register result = ToRegister(instr->result()); | 1560 Register result = ToRegister(instr->result()); |
1561 | 1561 |
1562 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1562 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
1563 __ test(input, Immediate(kSmiTagMask)); | 1563 __ test(input, Immediate(kSmiTagMask)); |
1564 NearLabel done, is_false; | 1564 NearLabel done, is_false; |
1565 __ j(zero, &is_false); | 1565 __ j(zero, &is_false); |
1566 __ CmpObjectType(input, instr->TestType(), result); | 1566 __ CmpObjectType(input, TestType(instr->hydrogen()), result); |
1567 __ j(NegateCondition(instr->BranchCondition()), &is_false); | 1567 __ j(NegateCondition(BranchCondition(instr->hydrogen())), &is_false); |
1568 __ mov(result, Handle<Object>(Heap::true_value())); | 1568 __ mov(result, Handle<Object>(Heap::true_value())); |
1569 __ jmp(&done); | 1569 __ jmp(&done); |
1570 __ bind(&is_false); | 1570 __ bind(&is_false); |
1571 __ mov(result, Handle<Object>(Heap::false_value())); | 1571 __ mov(result, Handle<Object>(Heap::false_value())); |
1572 __ bind(&done); | 1572 __ bind(&done); |
1573 } | 1573 } |
1574 | 1574 |
1575 | 1575 |
1576 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 1576 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
1577 Register input = ToRegister(instr->input()); | 1577 Register input = ToRegister(instr->input()); |
1578 Register temp = ToRegister(instr->temp()); | 1578 Register temp = ToRegister(instr->TempAt(0)); |
1579 | 1579 |
1580 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1580 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1581 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1581 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1582 | 1582 |
1583 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1583 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1584 | 1584 |
1585 __ test(input, Immediate(kSmiTagMask)); | 1585 __ test(input, Immediate(kSmiTagMask)); |
1586 __ j(zero, false_label); | 1586 __ j(zero, false_label); |
1587 | 1587 |
1588 __ CmpObjectType(input, instr->TestType(), temp); | 1588 __ CmpObjectType(input, TestType(instr->hydrogen()), temp); |
1589 EmitBranch(true_block, false_block, instr->BranchCondition()); | 1589 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); |
1590 } | 1590 } |
1591 | 1591 |
1592 | 1592 |
1593 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { | 1593 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { |
1594 Register input = ToRegister(instr->input()); | 1594 Register input = ToRegister(instr->input()); |
1595 Register result = ToRegister(instr->result()); | 1595 Register result = ToRegister(instr->result()); |
1596 | 1596 |
1597 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1597 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
1598 __ mov(result, Handle<Object>(Heap::true_value())); | 1598 __ mov(result, Handle<Object>(Heap::true_value())); |
1599 __ test(FieldOperand(input, String::kHashFieldOffset), | 1599 __ test(FieldOperand(input, String::kHashFieldOffset), |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1672 // comparison. | 1672 // comparison. |
1673 __ cmp(temp, class_name); | 1673 __ cmp(temp, class_name); |
1674 // End with the answer in the z flag. | 1674 // End with the answer in the z flag. |
1675 } | 1675 } |
1676 | 1676 |
1677 | 1677 |
1678 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { | 1678 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { |
1679 Register input = ToRegister(instr->input()); | 1679 Register input = ToRegister(instr->input()); |
1680 Register result = ToRegister(instr->result()); | 1680 Register result = ToRegister(instr->result()); |
1681 ASSERT(input.is(result)); | 1681 ASSERT(input.is(result)); |
1682 Register temp = ToRegister(instr->temporary()); | 1682 Register temp = ToRegister(instr->TempAt(0)); |
1683 Handle<String> class_name = instr->hydrogen()->class_name(); | 1683 Handle<String> class_name = instr->hydrogen()->class_name(); |
1684 NearLabel done; | 1684 NearLabel done; |
1685 Label is_true, is_false; | 1685 Label is_true, is_false; |
1686 | 1686 |
1687 EmitClassOfTest(&is_true, &is_false, class_name, input, temp, input); | 1687 EmitClassOfTest(&is_true, &is_false, class_name, input, temp, input); |
1688 | 1688 |
1689 __ j(not_equal, &is_false); | 1689 __ j(not_equal, &is_false); |
1690 | 1690 |
1691 __ bind(&is_true); | 1691 __ bind(&is_true); |
1692 __ mov(result, Handle<Object>(Heap::true_value())); | 1692 __ mov(result, Handle<Object>(Heap::true_value())); |
1693 __ jmp(&done); | 1693 __ jmp(&done); |
1694 | 1694 |
1695 __ bind(&is_false); | 1695 __ bind(&is_false); |
1696 __ mov(result, Handle<Object>(Heap::false_value())); | 1696 __ mov(result, Handle<Object>(Heap::false_value())); |
1697 __ bind(&done); | 1697 __ bind(&done); |
1698 } | 1698 } |
1699 | 1699 |
1700 | 1700 |
1701 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 1701 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
1702 Register input = ToRegister(instr->input()); | 1702 Register input = ToRegister(instr->input()); |
1703 Register temp = ToRegister(instr->temporary()); | 1703 Register temp = ToRegister(instr->TempAt(0)); |
1704 Register temp2 = ToRegister(instr->temporary2()); | 1704 Register temp2 = ToRegister(instr->TempAt(1)); |
1705 if (input.is(temp)) { | 1705 if (input.is(temp)) { |
1706 // Swap. | 1706 // Swap. |
1707 Register swapper = temp; | 1707 Register swapper = temp; |
1708 temp = temp2; | 1708 temp = temp2; |
1709 temp2 = swapper; | 1709 temp2 = swapper; |
1710 } | 1710 } |
1711 Handle<String> class_name = instr->hydrogen()->class_name(); | 1711 Handle<String> class_name = instr->hydrogen()->class_name(); |
1712 | 1712 |
1713 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1713 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1714 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1714 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1774 private: | 1774 private: |
1775 LInstanceOfKnownGlobal* instr_; | 1775 LInstanceOfKnownGlobal* instr_; |
1776 Label map_check_; | 1776 Label map_check_; |
1777 }; | 1777 }; |
1778 | 1778 |
1779 DeferredInstanceOfKnownGlobal* deferred; | 1779 DeferredInstanceOfKnownGlobal* deferred; |
1780 deferred = new DeferredInstanceOfKnownGlobal(this, instr); | 1780 deferred = new DeferredInstanceOfKnownGlobal(this, instr); |
1781 | 1781 |
1782 Label done, false_result; | 1782 Label done, false_result; |
1783 Register object = ToRegister(instr->input()); | 1783 Register object = ToRegister(instr->input()); |
1784 Register temp = ToRegister(instr->temp()); | 1784 Register temp = ToRegister(instr->TempAt(0)); |
1785 | 1785 |
1786 // A Smi is not instance of anything. | 1786 // A Smi is not instance of anything. |
1787 __ test(object, Immediate(kSmiTagMask)); | 1787 __ test(object, Immediate(kSmiTagMask)); |
1788 __ j(zero, &false_result, not_taken); | 1788 __ j(zero, &false_result, not_taken); |
1789 | 1789 |
1790 // This is the inlined call site instanceof cache. The two occourences of the | 1790 // This is the inlined call site instanceof cache. The two occourences of the |
1791 // hole value will be patched to the last map/result pair generated by the | 1791 // hole value will be patched to the last map/result pair generated by the |
1792 // instanceof stub. | 1792 // instanceof stub. |
1793 NearLabel cache_miss; | 1793 NearLabel cache_miss; |
1794 Register map = ToRegister(instr->temp()); | 1794 Register map = ToRegister(instr->TempAt(0)); |
1795 __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); | 1795 __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); |
1796 __ bind(deferred->map_check()); // Label for calculating code patching. | 1796 __ bind(deferred->map_check()); // Label for calculating code patching. |
1797 __ cmp(map, Factory::the_hole_value()); // Patched to cached map. | 1797 __ cmp(map, Factory::the_hole_value()); // Patched to cached map. |
1798 __ j(not_equal, &cache_miss, not_taken); | 1798 __ j(not_equal, &cache_miss, not_taken); |
1799 __ mov(eax, Factory::the_hole_value()); // Patched to either true or false. | 1799 __ mov(eax, Factory::the_hole_value()); // Patched to either true or false. |
1800 __ jmp(&done); | 1800 __ jmp(&done); |
1801 | 1801 |
1802 // The inlined call site cache did not match. Check null and string before | 1802 // The inlined call site cache did not match. Check null and string before |
1803 // calling the deferred code. | 1803 // calling the deferred code. |
1804 __ bind(&cache_miss); | 1804 __ bind(&cache_miss); |
(...skipping 27 matching lines...) Expand all Loading... |
1832 flags | InstanceofStub::kArgsInRegisters); | 1832 flags | InstanceofStub::kArgsInRegisters); |
1833 flags = static_cast<InstanceofStub::Flags>( | 1833 flags = static_cast<InstanceofStub::Flags>( |
1834 flags | InstanceofStub::kCallSiteInlineCheck); | 1834 flags | InstanceofStub::kCallSiteInlineCheck); |
1835 flags = static_cast<InstanceofStub::Flags>( | 1835 flags = static_cast<InstanceofStub::Flags>( |
1836 flags | InstanceofStub::kReturnTrueFalseObject); | 1836 flags | InstanceofStub::kReturnTrueFalseObject); |
1837 InstanceofStub stub(flags); | 1837 InstanceofStub stub(flags); |
1838 | 1838 |
1839 // Get the temp register reserved by the instruction. This needs to be edi as | 1839 // Get the temp register reserved by the instruction. This needs to be edi as |
1840 // its slot of the pushing of safepoint registers is used to communicate the | 1840 // its slot of the pushing of safepoint registers is used to communicate the |
1841 // offset to the location of the map check. | 1841 // offset to the location of the map check. |
1842 Register temp = ToRegister(instr->temp()); | 1842 Register temp = ToRegister(instr->TempAt(0)); |
1843 ASSERT(temp.is(edi)); | 1843 ASSERT(temp.is(edi)); |
1844 __ mov(InstanceofStub::right(), Immediate(instr->function())); | 1844 __ mov(InstanceofStub::right(), Immediate(instr->function())); |
1845 static const int kAdditionalDelta = 13; | 1845 static const int kAdditionalDelta = 13; |
1846 int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; | 1846 int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; |
1847 Label before_push_delta; | 1847 Label before_push_delta; |
1848 __ bind(&before_push_delta); | 1848 __ bind(&before_push_delta); |
1849 __ mov(temp, Immediate(delta)); | 1849 __ mov(temp, Immediate(delta)); |
1850 __ mov(Operand(esp, EspIndexForPushAll(temp) * kPointerSize), temp); | 1850 __ mov(Operand(esp, EspIndexForPushAll(temp) * kPointerSize), temp); |
1851 __ call(stub.GetCode(), RelocInfo::CODE_TARGET); | 1851 __ call(stub.GetCode(), RelocInfo::CODE_TARGET); |
1852 ASSERT_EQ(kAdditionalDelta, | 1852 ASSERT_EQ(kAdditionalDelta, |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1966 ASSERT(ToRegister(instr->result()).is(eax)); | 1966 ASSERT(ToRegister(instr->result()).is(eax)); |
1967 | 1967 |
1968 __ mov(ecx, instr->name()); | 1968 __ mov(ecx, instr->name()); |
1969 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1969 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
1970 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 1970 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
1971 } | 1971 } |
1972 | 1972 |
1973 | 1973 |
1974 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { | 1974 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { |
1975 Register function = ToRegister(instr->function()); | 1975 Register function = ToRegister(instr->function()); |
1976 Register temp = ToRegister(instr->temporary()); | 1976 Register temp = ToRegister(instr->TempAt(0)); |
1977 Register result = ToRegister(instr->result()); | 1977 Register result = ToRegister(instr->result()); |
1978 | 1978 |
1979 // Check that the function really is a function. | 1979 // Check that the function really is a function. |
1980 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); | 1980 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); |
1981 DeoptimizeIf(not_equal, instr->environment()); | 1981 DeoptimizeIf(not_equal, instr->environment()); |
1982 | 1982 |
1983 // Check whether the function has an instance prototype. | 1983 // Check whether the function has an instance prototype. |
1984 NearLabel non_instance; | 1984 NearLabel non_instance; |
1985 __ test_b(FieldOperand(result, Map::kBitFieldOffset), | 1985 __ test_b(FieldOperand(result, Map::kBitFieldOffset), |
1986 1 << Map::kHasNonInstancePrototype); | 1986 1 << Map::kHasNonInstancePrototype); |
(...skipping 616 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2603 int offset = instr->offset(); | 2603 int offset = instr->offset(); |
2604 | 2604 |
2605 if (!instr->transition().is_null()) { | 2605 if (!instr->transition().is_null()) { |
2606 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); | 2606 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); |
2607 } | 2607 } |
2608 | 2608 |
2609 // Do the store. | 2609 // Do the store. |
2610 if (instr->is_in_object()) { | 2610 if (instr->is_in_object()) { |
2611 __ mov(FieldOperand(object, offset), value); | 2611 __ mov(FieldOperand(object, offset), value); |
2612 if (instr->needs_write_barrier()) { | 2612 if (instr->needs_write_barrier()) { |
2613 Register temp = ToRegister(instr->temp()); | 2613 Register temp = ToRegister(instr->TempAt(0)); |
2614 // Update the write barrier for the object for in-object properties. | 2614 // Update the write barrier for the object for in-object properties. |
2615 __ RecordWrite(object, offset, value, temp); | 2615 __ RecordWrite(object, offset, value, temp); |
2616 } | 2616 } |
2617 } else { | 2617 } else { |
2618 Register temp = ToRegister(instr->temp()); | 2618 Register temp = ToRegister(instr->TempAt(0)); |
2619 __ mov(temp, FieldOperand(object, JSObject::kPropertiesOffset)); | 2619 __ mov(temp, FieldOperand(object, JSObject::kPropertiesOffset)); |
2620 __ mov(FieldOperand(temp, offset), value); | 2620 __ mov(FieldOperand(temp, offset), value); |
2621 if (instr->needs_write_barrier()) { | 2621 if (instr->needs_write_barrier()) { |
2622 // Update the write barrier for the properties array. | 2622 // Update the write barrier for the properties array. |
2623 // object is used as a scratch register. | 2623 // object is used as a scratch register. |
2624 __ RecordWrite(temp, offset, value, object); | 2624 __ RecordWrite(temp, offset, value, object); |
2625 } | 2625 } |
2626 } | 2626 } |
2627 } | 2627 } |
2628 | 2628 |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2755 public: | 2755 public: |
2756 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 2756 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
2757 : LDeferredCode(codegen), instr_(instr) { } | 2757 : LDeferredCode(codegen), instr_(instr) { } |
2758 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } | 2758 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } |
2759 private: | 2759 private: |
2760 LNumberTagD* instr_; | 2760 LNumberTagD* instr_; |
2761 }; | 2761 }; |
2762 | 2762 |
2763 XMMRegister input_reg = ToDoubleRegister(instr->input()); | 2763 XMMRegister input_reg = ToDoubleRegister(instr->input()); |
2764 Register reg = ToRegister(instr->result()); | 2764 Register reg = ToRegister(instr->result()); |
2765 Register tmp = ToRegister(instr->temp()); | 2765 Register tmp = ToRegister(instr->TempAt(0)); |
2766 | 2766 |
2767 DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); | 2767 DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); |
2768 if (FLAG_inline_new) { | 2768 if (FLAG_inline_new) { |
2769 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry()); | 2769 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry()); |
2770 } else { | 2770 } else { |
2771 __ jmp(deferred->entry()); | 2771 __ jmp(deferred->entry()); |
2772 } | 2772 } |
2773 __ bind(deferred->exit()); | 2773 __ bind(deferred->exit()); |
2774 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); | 2774 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); |
2775 } | 2775 } |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2896 | 2896 |
2897 // Reserve space for 64 bit answer. | 2897 // Reserve space for 64 bit answer. |
2898 __ bind(&convert); | 2898 __ bind(&convert); |
2899 __ sub(Operand(esp), Immediate(kDoubleSize)); | 2899 __ sub(Operand(esp), Immediate(kDoubleSize)); |
2900 // Do conversion, which cannot fail because we checked the exponent. | 2900 // Do conversion, which cannot fail because we checked the exponent. |
2901 __ fisttp_d(Operand(esp, 0)); | 2901 __ fisttp_d(Operand(esp, 0)); |
2902 __ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result. | 2902 __ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result. |
2903 __ add(Operand(esp), Immediate(kDoubleSize)); | 2903 __ add(Operand(esp), Immediate(kDoubleSize)); |
2904 } else { | 2904 } else { |
2905 NearLabel deopt; | 2905 NearLabel deopt; |
2906 XMMRegister xmm_temp = ToDoubleRegister(instr->temp()); | 2906 XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); |
2907 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 2907 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
2908 __ cvttsd2si(input_reg, Operand(xmm0)); | 2908 __ cvttsd2si(input_reg, Operand(xmm0)); |
2909 __ cmp(input_reg, 0x80000000u); | 2909 __ cmp(input_reg, 0x80000000u); |
2910 __ j(not_equal, &done); | 2910 __ j(not_equal, &done); |
2911 // Check if the input was 0x8000000 (kMinInt). | 2911 // Check if the input was 0x8000000 (kMinInt). |
2912 // If no, then we got an overflow and we deoptimize. | 2912 // If no, then we got an overflow and we deoptimize. |
2913 ExternalReference min_int = ExternalReference::address_of_min_int(); | 2913 ExternalReference min_int = ExternalReference::address_of_min_int(); |
2914 __ movdbl(xmm_temp, Operand::StaticVariable(min_int)); | 2914 __ movdbl(xmm_temp, Operand::StaticVariable(min_int)); |
2915 __ ucomisd(xmm_temp, xmm0); | 2915 __ ucomisd(xmm_temp, xmm0); |
2916 DeoptimizeIf(not_equal, instr->environment()); | 2916 DeoptimizeIf(not_equal, instr->environment()); |
2917 DeoptimizeIf(parity_even, instr->environment()); // NaN. | 2917 DeoptimizeIf(parity_even, instr->environment()); // NaN. |
2918 } | 2918 } |
2919 } else { | 2919 } else { |
2920 // Deoptimize if we don't have a heap number. | 2920 // Deoptimize if we don't have a heap number. |
2921 DeoptimizeIf(not_equal, instr->environment()); | 2921 DeoptimizeIf(not_equal, instr->environment()); |
2922 | 2922 |
2923 XMMRegister xmm_temp = ToDoubleRegister(instr->temp()); | 2923 XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); |
2924 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 2924 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
2925 __ cvttsd2si(input_reg, Operand(xmm0)); | 2925 __ cvttsd2si(input_reg, Operand(xmm0)); |
2926 __ cvtsi2sd(xmm_temp, Operand(input_reg)); | 2926 __ cvtsi2sd(xmm_temp, Operand(input_reg)); |
2927 __ ucomisd(xmm0, xmm_temp); | 2927 __ ucomisd(xmm0, xmm_temp); |
2928 DeoptimizeIf(not_equal, instr->environment()); | 2928 DeoptimizeIf(not_equal, instr->environment()); |
2929 DeoptimizeIf(parity_even, instr->environment()); // NaN. | 2929 DeoptimizeIf(parity_even, instr->environment()); // NaN. |
2930 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 2930 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
2931 __ test(input_reg, Operand(input_reg)); | 2931 __ test(input_reg, Operand(input_reg)); |
2932 __ j(not_zero, &done); | 2932 __ j(not_zero, &done); |
2933 __ movmskpd(input_reg, xmm0); | 2933 __ movmskpd(input_reg, xmm0); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3004 DeoptimizeIf(no_condition, instr->environment()); | 3004 DeoptimizeIf(no_condition, instr->environment()); |
3005 __ bind(&convert); | 3005 __ bind(&convert); |
3006 // Do conversion, which cannot fail because we checked the exponent. | 3006 // Do conversion, which cannot fail because we checked the exponent. |
3007 __ fld_d(Operand(esp, 0)); | 3007 __ fld_d(Operand(esp, 0)); |
3008 __ fisttp_d(Operand(esp, 0)); | 3008 __ fisttp_d(Operand(esp, 0)); |
3009 __ mov(result_reg, Operand(esp, 0)); // Low word of answer is the result. | 3009 __ mov(result_reg, Operand(esp, 0)); // Low word of answer is the result. |
3010 __ add(Operand(esp), Immediate(kDoubleSize)); | 3010 __ add(Operand(esp), Immediate(kDoubleSize)); |
3011 __ bind(&done); | 3011 __ bind(&done); |
3012 } else { | 3012 } else { |
3013 NearLabel done; | 3013 NearLabel done; |
3014 Register temp_reg = ToRegister(instr->temporary()); | 3014 Register temp_reg = ToRegister(instr->TempAt(0)); |
3015 XMMRegister xmm_scratch = xmm0; | 3015 XMMRegister xmm_scratch = xmm0; |
3016 | 3016 |
3017 // If cvttsd2si succeeded, we're done. Otherwise, we attempt | 3017 // If cvttsd2si succeeded, we're done. Otherwise, we attempt |
3018 // manual conversion. | 3018 // manual conversion. |
3019 __ j(not_equal, &done); | 3019 __ j(not_equal, &done); |
3020 | 3020 |
3021 // Get high 32 bits of the input in result_reg and temp_reg. | 3021 // Get high 32 bits of the input in result_reg and temp_reg. |
3022 __ pshufd(xmm_scratch, input_reg, 1); | 3022 __ pshufd(xmm_scratch, input_reg, 1); |
3023 __ movd(Operand(temp_reg), xmm_scratch); | 3023 __ movd(Operand(temp_reg), xmm_scratch); |
3024 __ mov(result_reg, temp_reg); | 3024 __ mov(result_reg, temp_reg); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3092 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 3092 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
3093 LOperand* input = instr->input(); | 3093 LOperand* input = instr->input(); |
3094 ASSERT(input->IsRegister()); | 3094 ASSERT(input->IsRegister()); |
3095 __ test(ToRegister(input), Immediate(kSmiTagMask)); | 3095 __ test(ToRegister(input), Immediate(kSmiTagMask)); |
3096 DeoptimizeIf(instr->condition(), instr->environment()); | 3096 DeoptimizeIf(instr->condition(), instr->environment()); |
3097 } | 3097 } |
3098 | 3098 |
3099 | 3099 |
3100 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 3100 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
3101 Register input = ToRegister(instr->input()); | 3101 Register input = ToRegister(instr->input()); |
3102 Register temp = ToRegister(instr->temp()); | 3102 Register temp = ToRegister(instr->TempAt(0)); |
3103 InstanceType first = instr->hydrogen()->first(); | 3103 InstanceType first = instr->hydrogen()->first(); |
3104 InstanceType last = instr->hydrogen()->last(); | 3104 InstanceType last = instr->hydrogen()->last(); |
3105 | 3105 |
3106 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); | 3106 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); |
3107 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), | 3107 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), |
3108 static_cast<int8_t>(first)); | 3108 static_cast<int8_t>(first)); |
3109 | 3109 |
3110 // If there is only one type in the interval check for equality. | 3110 // If there is only one type in the interval check for equality. |
3111 if (first == last) { | 3111 if (first == last) { |
3112 DeoptimizeIf(not_equal, instr->environment()); | 3112 DeoptimizeIf(not_equal, instr->environment()); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3145 Handle<JSGlobalPropertyCell> cell = | 3145 Handle<JSGlobalPropertyCell> cell = |
3146 Factory::NewJSGlobalPropertyCell(prototype); | 3146 Factory::NewJSGlobalPropertyCell(prototype); |
3147 __ mov(result, Operand::Cell(cell)); | 3147 __ mov(result, Operand::Cell(cell)); |
3148 } else { | 3148 } else { |
3149 __ mov(result, prototype); | 3149 __ mov(result, prototype); |
3150 } | 3150 } |
3151 } | 3151 } |
3152 | 3152 |
3153 | 3153 |
3154 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { | 3154 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { |
3155 Register reg = ToRegister(instr->temp()); | 3155 Register reg = ToRegister(instr->TempAt(0)); |
3156 | 3156 |
3157 Handle<JSObject> holder = instr->holder(); | 3157 Handle<JSObject> holder = instr->holder(); |
3158 Handle<Map> receiver_map = instr->receiver_map(); | 3158 Handle<Map> receiver_map = instr->receiver_map(); |
3159 Handle<JSObject> current_prototype(JSObject::cast(receiver_map->prototype())); | 3159 Handle<JSObject> current_prototype(JSObject::cast(receiver_map->prototype())); |
3160 | 3160 |
3161 // Load prototype object. | 3161 // Load prototype object. |
3162 LoadPrototype(reg, current_prototype); | 3162 LoadPrototype(reg, current_prototype); |
3163 | 3163 |
3164 // Check prototype maps up to the holder. | 3164 // Check prototype maps up to the holder. |
3165 while (!current_prototype.is_identical_to(holder)) { | 3165 while (!current_prototype.is_identical_to(holder)) { |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3476 ASSERT(!environment->HasBeenRegistered()); | 3476 ASSERT(!environment->HasBeenRegistered()); |
3477 RegisterEnvironmentForDeoptimization(environment); | 3477 RegisterEnvironmentForDeoptimization(environment); |
3478 ASSERT(osr_pc_offset_ == -1); | 3478 ASSERT(osr_pc_offset_ == -1); |
3479 osr_pc_offset_ = masm()->pc_offset(); | 3479 osr_pc_offset_ = masm()->pc_offset(); |
3480 } | 3480 } |
3481 | 3481 |
3482 | 3482 |
3483 #undef __ | 3483 #undef __ |
3484 | 3484 |
3485 } } // namespace v8::internal | 3485 } } // namespace v8::internal |
OLD | NEW |