| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 638 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 649 return ToX87Register(op->index()); | 649 return ToX87Register(op->index()); |
| 650 } | 650 } |
| 651 | 651 |
| 652 | 652 |
| 653 XMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const { | 653 XMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const { |
| 654 ASSERT(op->IsDoubleRegister()); | 654 ASSERT(op->IsDoubleRegister()); |
| 655 return ToDoubleRegister(op->index()); | 655 return ToDoubleRegister(op->index()); |
| 656 } | 656 } |
| 657 | 657 |
| 658 | 658 |
| 659 int LCodeGen::ToInteger32(LConstantOperand* op) const { | 659 int32_t LCodeGen::ToInteger32(LConstantOperand* op) const { |
| 660 HConstant* constant = chunk_->LookupConstant(op); | 660 return ToRepresentation(op, Representation::Integer32()); |
| 661 return constant->Integer32Value(); | |
| 662 } | 661 } |
| 663 | 662 |
| 664 | 663 |
| 664 int32_t LCodeGen::ToRepresentation(LConstantOperand* op, |
| 665 const Representation& r) const { |
| 666 HConstant* constant = chunk_->LookupConstant(op); |
| 667 int32_t value = constant->Integer32Value(); |
| 668 if (r.IsInteger32()) return value; |
| 669 ASSERT(r.IsSmiOrTagged()); |
| 670 return reinterpret_cast<int32_t>(Smi::FromInt(value)); |
| 671 } |
| 672 |
| 673 |
| 665 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { | 674 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { |
| 666 HConstant* constant = chunk_->LookupConstant(op); | 675 HConstant* constant = chunk_->LookupConstant(op); |
| 667 ASSERT(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged()); | 676 ASSERT(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged()); |
| 668 return constant->handle(); | 677 return constant->handle(); |
| 669 } | 678 } |
| 670 | 679 |
| 671 | 680 |
| 672 double LCodeGen::ToDouble(LConstantOperand* op) const { | 681 double LCodeGen::ToDouble(LConstantOperand* op) const { |
| 673 HConstant* constant = chunk_->LookupConstant(op); | 682 HConstant* constant = chunk_->LookupConstant(op); |
| 674 ASSERT(constant->HasDoubleValue()); | 683 ASSERT(constant->HasDoubleValue()); |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 996 | 1005 |
| 997 void LCodeGen::DeoptimizeIf(Condition cc, | 1006 void LCodeGen::DeoptimizeIf(Condition cc, |
| 998 LEnvironment* environment) { | 1007 LEnvironment* environment) { |
| 999 Deoptimizer::BailoutType bailout_type = info()->IsStub() | 1008 Deoptimizer::BailoutType bailout_type = info()->IsStub() |
| 1000 ? Deoptimizer::LAZY | 1009 ? Deoptimizer::LAZY |
| 1001 : Deoptimizer::EAGER; | 1010 : Deoptimizer::EAGER; |
| 1002 DeoptimizeIf(cc, environment, bailout_type); | 1011 DeoptimizeIf(cc, environment, bailout_type); |
| 1003 } | 1012 } |
| 1004 | 1013 |
| 1005 | 1014 |
| 1006 void LCodeGen::SoftDeoptimize(LEnvironment* environment) { | |
| 1007 ASSERT(!info()->IsStub()); | |
| 1008 DeoptimizeIf(no_condition, environment, Deoptimizer::SOFT); | |
| 1009 } | |
| 1010 | |
| 1011 | |
| 1012 void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) { | 1015 void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) { |
| 1013 ZoneList<Handle<Map> > maps(1, zone()); | 1016 ZoneList<Handle<Map> > maps(1, zone()); |
| 1014 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | 1017 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
| 1015 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { | 1018 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { |
| 1016 RelocInfo::Mode mode = it.rinfo()->rmode(); | 1019 RelocInfo::Mode mode = it.rinfo()->rmode(); |
| 1017 if (mode == RelocInfo::EMBEDDED_OBJECT && | 1020 if (mode == RelocInfo::EMBEDDED_OBJECT && |
| 1018 it.rinfo()->target_object()->IsMap()) { | 1021 it.rinfo()->target_object()->IsMap()) { |
| 1019 Handle<Map> map(Map::cast(it.rinfo()->target_object())); | 1022 Handle<Map> map(Map::cast(it.rinfo()->target_object())); |
| 1020 if (map->CanTransition()) { | 1023 if (map->CanTransition()) { |
| 1021 maps.Add(map, zone()); | 1024 maps.Add(map, zone()); |
| (...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1618 __ shl(left, 4); | 1621 __ shl(left, 4); |
| 1619 break; | 1622 break; |
| 1620 default: | 1623 default: |
| 1621 __ imul(left, left, constant); | 1624 __ imul(left, left, constant); |
| 1622 break; | 1625 break; |
| 1623 } | 1626 } |
| 1624 } else { | 1627 } else { |
| 1625 __ imul(left, left, constant); | 1628 __ imul(left, left, constant); |
| 1626 } | 1629 } |
| 1627 } else { | 1630 } else { |
| 1631 if (instr->hydrogen()->representation().IsSmi()) { |
| 1632 __ SmiUntag(left); |
| 1633 } |
| 1628 __ imul(left, ToOperand(right)); | 1634 __ imul(left, ToOperand(right)); |
| 1629 } | 1635 } |
| 1630 | 1636 |
| 1631 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1637 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 1632 DeoptimizeIf(overflow, instr->environment()); | 1638 DeoptimizeIf(overflow, instr->environment()); |
| 1633 } | 1639 } |
| 1634 | 1640 |
| 1635 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1641 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1636 // Bail out if the result is supposed to be negative zero. | 1642 // Bail out if the result is supposed to be negative zero. |
| 1637 Label done; | 1643 Label done; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1654 } | 1660 } |
| 1655 | 1661 |
| 1656 | 1662 |
| 1657 void LCodeGen::DoBitI(LBitI* instr) { | 1663 void LCodeGen::DoBitI(LBitI* instr) { |
| 1658 LOperand* left = instr->left(); | 1664 LOperand* left = instr->left(); |
| 1659 LOperand* right = instr->right(); | 1665 LOperand* right = instr->right(); |
| 1660 ASSERT(left->Equals(instr->result())); | 1666 ASSERT(left->Equals(instr->result())); |
| 1661 ASSERT(left->IsRegister()); | 1667 ASSERT(left->IsRegister()); |
| 1662 | 1668 |
| 1663 if (right->IsConstantOperand()) { | 1669 if (right->IsConstantOperand()) { |
| 1664 int right_operand = ToInteger32(LConstantOperand::cast(right)); | 1670 int right_operand = ToRepresentation(LConstantOperand::cast(right), |
| 1671 instr->hydrogen()->representation()); |
| 1665 switch (instr->op()) { | 1672 switch (instr->op()) { |
| 1666 case Token::BIT_AND: | 1673 case Token::BIT_AND: |
| 1667 __ and_(ToRegister(left), right_operand); | 1674 __ and_(ToRegister(left), right_operand); |
| 1668 break; | 1675 break; |
| 1669 case Token::BIT_OR: | 1676 case Token::BIT_OR: |
| 1670 __ or_(ToRegister(left), right_operand); | 1677 __ or_(ToRegister(left), right_operand); |
| 1671 break; | 1678 break; |
| 1672 case Token::BIT_XOR: | 1679 case Token::BIT_XOR: |
| 1673 __ xor_(ToRegister(left), right_operand); | 1680 __ xor_(ToRegister(left), right_operand); |
| 1674 break; | 1681 break; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1748 case Token::SHR: | 1755 case Token::SHR: |
| 1749 if (shift_count == 0 && instr->can_deopt()) { | 1756 if (shift_count == 0 && instr->can_deopt()) { |
| 1750 __ test(ToRegister(left), Immediate(0x80000000)); | 1757 __ test(ToRegister(left), Immediate(0x80000000)); |
| 1751 DeoptimizeIf(not_zero, instr->environment()); | 1758 DeoptimizeIf(not_zero, instr->environment()); |
| 1752 } else { | 1759 } else { |
| 1753 __ shr(ToRegister(left), shift_count); | 1760 __ shr(ToRegister(left), shift_count); |
| 1754 } | 1761 } |
| 1755 break; | 1762 break; |
| 1756 case Token::SHL: | 1763 case Token::SHL: |
| 1757 if (shift_count != 0) { | 1764 if (shift_count != 0) { |
| 1758 __ shl(ToRegister(left), shift_count); | 1765 if (instr->hydrogen_value()->representation().IsSmi() && |
| 1766 instr->can_deopt()) { |
| 1767 __ shl(ToRegister(left), shift_count - 1); |
| 1768 __ SmiTag(ToRegister(left)); |
| 1769 DeoptimizeIf(overflow, instr->environment()); |
| 1770 } else { |
| 1771 __ shl(ToRegister(left), shift_count); |
| 1772 } |
| 1759 } | 1773 } |
| 1760 break; | 1774 break; |
| 1761 default: | 1775 default: |
| 1762 UNREACHABLE(); | 1776 UNREACHABLE(); |
| 1763 break; | 1777 break; |
| 1764 } | 1778 } |
| 1765 } | 1779 } |
| 1766 } | 1780 } |
| 1767 | 1781 |
| 1768 | 1782 |
| 1769 void LCodeGen::DoSubI(LSubI* instr) { | 1783 void LCodeGen::DoSubI(LSubI* instr) { |
| 1770 LOperand* left = instr->left(); | 1784 LOperand* left = instr->left(); |
| 1771 LOperand* right = instr->right(); | 1785 LOperand* right = instr->right(); |
| 1772 ASSERT(left->Equals(instr->result())); | 1786 ASSERT(left->Equals(instr->result())); |
| 1773 | 1787 |
| 1774 if (right->IsConstantOperand()) { | 1788 if (right->IsConstantOperand()) { |
| 1775 __ sub(ToOperand(left), ToInteger32Immediate(right)); | 1789 __ sub(ToOperand(left), |
| 1790 ToImmediate(right, instr->hydrogen()->representation())); |
| 1776 } else { | 1791 } else { |
| 1777 __ sub(ToRegister(left), ToOperand(right)); | 1792 __ sub(ToRegister(left), ToOperand(right)); |
| 1778 } | 1793 } |
| 1779 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1794 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 1780 DeoptimizeIf(overflow, instr->environment()); | 1795 DeoptimizeIf(overflow, instr->environment()); |
| 1781 } | 1796 } |
| 1782 } | 1797 } |
| 1783 | 1798 |
| 1784 | 1799 |
| 1785 void LCodeGen::DoConstantI(LConstantI* instr) { | 1800 void LCodeGen::DoConstantI(LConstantI* instr) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1835 } | 1850 } |
| 1836 } | 1851 } |
| 1837 } | 1852 } |
| 1838 } | 1853 } |
| 1839 | 1854 |
| 1840 | 1855 |
| 1841 void LCodeGen::DoConstantT(LConstantT* instr) { | 1856 void LCodeGen::DoConstantT(LConstantT* instr) { |
| 1842 Register reg = ToRegister(instr->result()); | 1857 Register reg = ToRegister(instr->result()); |
| 1843 Handle<Object> handle = instr->value(); | 1858 Handle<Object> handle = instr->value(); |
| 1844 AllowDeferredHandleDereference smi_check; | 1859 AllowDeferredHandleDereference smi_check; |
| 1845 if (handle->IsHeapObject()) { | 1860 __ LoadObject(reg, handle); |
| 1846 __ LoadHeapObject(reg, Handle<HeapObject>::cast(handle)); | |
| 1847 } else { | |
| 1848 __ Set(reg, Immediate(handle)); | |
| 1849 } | |
| 1850 } | 1861 } |
| 1851 | 1862 |
| 1852 | 1863 |
| 1853 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { | 1864 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { |
| 1854 Register result = ToRegister(instr->result()); | 1865 Register result = ToRegister(instr->result()); |
| 1855 Register map = ToRegister(instr->value()); | 1866 Register map = ToRegister(instr->value()); |
| 1856 __ EnumLength(result, map); | 1867 __ EnumLength(result, map); |
| 1857 } | 1868 } |
| 1858 | 1869 |
| 1859 | 1870 |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1978 } | 1989 } |
| 1979 } | 1990 } |
| 1980 | 1991 |
| 1981 | 1992 |
| 1982 void LCodeGen::DoAddI(LAddI* instr) { | 1993 void LCodeGen::DoAddI(LAddI* instr) { |
| 1983 LOperand* left = instr->left(); | 1994 LOperand* left = instr->left(); |
| 1984 LOperand* right = instr->right(); | 1995 LOperand* right = instr->right(); |
| 1985 | 1996 |
| 1986 if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) { | 1997 if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) { |
| 1987 if (right->IsConstantOperand()) { | 1998 if (right->IsConstantOperand()) { |
| 1988 int32_t offset = ToInteger32(LConstantOperand::cast(right)); | 1999 int32_t offset = ToRepresentation(LConstantOperand::cast(right), |
| 2000 instr->hydrogen()->representation()); |
| 1989 __ lea(ToRegister(instr->result()), MemOperand(ToRegister(left), offset)); | 2001 __ lea(ToRegister(instr->result()), MemOperand(ToRegister(left), offset)); |
| 1990 } else { | 2002 } else { |
| 1991 Operand address(ToRegister(left), ToRegister(right), times_1, 0); | 2003 Operand address(ToRegister(left), ToRegister(right), times_1, 0); |
| 1992 __ lea(ToRegister(instr->result()), address); | 2004 __ lea(ToRegister(instr->result()), address); |
| 1993 } | 2005 } |
| 1994 } else { | 2006 } else { |
| 1995 if (right->IsConstantOperand()) { | 2007 if (right->IsConstantOperand()) { |
| 1996 __ add(ToOperand(left), ToInteger32Immediate(right)); | 2008 __ add(ToOperand(left), |
| 2009 ToImmediate(right, instr->hydrogen()->representation())); |
| 1997 } else { | 2010 } else { |
| 1998 __ add(ToRegister(left), ToOperand(right)); | 2011 __ add(ToRegister(left), ToOperand(right)); |
| 1999 } | 2012 } |
| 2000 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 2013 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 2001 DeoptimizeIf(overflow, instr->environment()); | 2014 DeoptimizeIf(overflow, instr->environment()); |
| 2002 } | 2015 } |
| 2003 } | 2016 } |
| 2004 } | 2017 } |
| 2005 | 2018 |
| 2006 | 2019 |
| 2007 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { | 2020 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
| 2008 CpuFeatureScope scope(masm(), SSE2); | 2021 CpuFeatureScope scope(masm(), SSE2); |
| 2009 LOperand* left = instr->left(); | 2022 LOperand* left = instr->left(); |
| 2010 LOperand* right = instr->right(); | 2023 LOperand* right = instr->right(); |
| 2011 ASSERT(left->Equals(instr->result())); | 2024 ASSERT(left->Equals(instr->result())); |
| 2012 HMathMinMax::Operation operation = instr->hydrogen()->operation(); | 2025 HMathMinMax::Operation operation = instr->hydrogen()->operation(); |
| 2013 if (instr->hydrogen()->representation().IsInteger32()) { | 2026 if (instr->hydrogen()->representation().IsSmiOrInteger32()) { |
| 2014 Label return_left; | 2027 Label return_left; |
| 2015 Condition condition = (operation == HMathMinMax::kMathMin) | 2028 Condition condition = (operation == HMathMinMax::kMathMin) |
| 2016 ? less_equal | 2029 ? less_equal |
| 2017 : greater_equal; | 2030 : greater_equal; |
| 2018 if (right->IsConstantOperand()) { | 2031 if (right->IsConstantOperand()) { |
| 2019 Operand left_op = ToOperand(left); | 2032 Operand left_op = ToOperand(left); |
| 2020 Immediate right_imm = ToInteger32Immediate(right); | 2033 Immediate immediate = ToImmediate(LConstantOperand::cast(instr->right()), |
| 2021 __ cmp(left_op, right_imm); | 2034 instr->hydrogen()->representation()); |
| 2035 __ cmp(left_op, immediate); |
| 2022 __ j(condition, &return_left, Label::kNear); | 2036 __ j(condition, &return_left, Label::kNear); |
| 2023 __ mov(left_op, right_imm); | 2037 __ mov(left_op, immediate); |
| 2024 } else { | 2038 } else { |
| 2025 Register left_reg = ToRegister(left); | 2039 Register left_reg = ToRegister(left); |
| 2026 Operand right_op = ToOperand(right); | 2040 Operand right_op = ToOperand(right); |
| 2027 __ cmp(left_reg, right_op); | 2041 __ cmp(left_reg, right_op); |
| 2028 __ j(condition, &return_left, Label::kNear); | 2042 __ j(condition, &return_left, Label::kNear); |
| 2029 __ mov(left_reg, right_op); | 2043 __ mov(left_reg, right_op); |
| 2030 } | 2044 } |
| 2031 __ bind(&return_left); | 2045 __ bind(&return_left); |
| 2032 } else { | 2046 } else { |
| 2033 ASSERT(instr->hydrogen()->representation().IsDouble()); | 2047 ASSERT(instr->hydrogen()->representation().IsDouble()); |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2381 EmitGoto(next_block); | 2395 EmitGoto(next_block); |
| 2382 } else { | 2396 } else { |
| 2383 if (instr->is_double()) { | 2397 if (instr->is_double()) { |
| 2384 CpuFeatureScope scope(masm(), SSE2); | 2398 CpuFeatureScope scope(masm(), SSE2); |
| 2385 // Don't base result on EFLAGS when a NaN is involved. Instead | 2399 // Don't base result on EFLAGS when a NaN is involved. Instead |
| 2386 // jump to the false block. | 2400 // jump to the false block. |
| 2387 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); | 2401 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); |
| 2388 __ j(parity_even, instr->FalseLabel(chunk_)); | 2402 __ j(parity_even, instr->FalseLabel(chunk_)); |
| 2389 } else { | 2403 } else { |
| 2390 if (right->IsConstantOperand()) { | 2404 if (right->IsConstantOperand()) { |
| 2391 int32_t const_value = ToInteger32(LConstantOperand::cast(right)); | 2405 __ cmp(ToOperand(left), |
| 2392 if (instr->hydrogen_value()->representation().IsSmi()) { | 2406 ToImmediate(right, instr->hydrogen()->representation())); |
| 2393 __ cmp(ToOperand(left), Immediate(Smi::FromInt(const_value))); | |
| 2394 } else { | |
| 2395 __ cmp(ToOperand(left), Immediate(const_value)); | |
| 2396 } | |
| 2397 } else if (left->IsConstantOperand()) { | 2407 } else if (left->IsConstantOperand()) { |
| 2398 int32_t const_value = ToInteger32(LConstantOperand::cast(left)); | 2408 __ cmp(ToOperand(right), |
| 2399 if (instr->hydrogen_value()->representation().IsSmi()) { | 2409 ToImmediate(left, instr->hydrogen()->representation())); |
| 2400 __ cmp(ToOperand(right), Immediate(Smi::FromInt(const_value))); | |
| 2401 } else { | |
| 2402 __ cmp(ToOperand(right), Immediate(const_value)); | |
| 2403 } | |
| 2404 // We transposed the operands. Reverse the condition. | 2410 // We transposed the operands. Reverse the condition. |
| 2405 cc = ReverseCondition(cc); | 2411 cc = ReverseCondition(cc); |
| 2406 } else { | 2412 } else { |
| 2407 __ cmp(ToRegister(left), ToOperand(right)); | 2413 __ cmp(ToRegister(left), ToOperand(right)); |
| 2408 } | 2414 } |
| 2409 } | 2415 } |
| 2410 EmitBranch(instr, cc); | 2416 EmitBranch(instr, cc); |
| 2411 } | 2417 } |
| 2412 } | 2418 } |
| 2413 | 2419 |
| 2414 | 2420 |
| 2415 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { | 2421 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { |
| 2416 Register left = ToRegister(instr->left()); | 2422 Register left = ToRegister(instr->left()); |
| 2417 | 2423 |
| 2418 if (instr->right()->IsConstantOperand()) { | 2424 if (instr->right()->IsConstantOperand()) { |
| 2419 Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right())); | 2425 Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right())); |
| 2420 __ CmpObject(left, right); | 2426 __ CmpObject(left, right); |
| 2421 } else { | 2427 } else { |
| 2422 Operand right = ToOperand(instr->right()); | 2428 Operand right = ToOperand(instr->right()); |
| 2423 __ cmp(left, right); | 2429 __ cmp(left, right); |
| 2424 } | 2430 } |
| 2425 EmitBranch(instr, equal); | 2431 EmitBranch(instr, equal); |
| 2426 } | 2432 } |
| 2427 | 2433 |
| 2428 | 2434 |
| 2429 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { | |
| 2430 Register left = ToRegister(instr->left()); | |
| 2431 | |
| 2432 __ cmp(left, instr->hydrogen()->right()); | |
| 2433 EmitBranch(instr, equal); | |
| 2434 } | |
| 2435 | |
| 2436 | |
| 2437 Condition LCodeGen::EmitIsObject(Register input, | 2435 Condition LCodeGen::EmitIsObject(Register input, |
| 2438 Register temp1, | 2436 Register temp1, |
| 2439 Label* is_not_object, | 2437 Label* is_not_object, |
| 2440 Label* is_object) { | 2438 Label* is_object) { |
| 2441 __ JumpIfSmi(input, is_not_object); | 2439 __ JumpIfSmi(input, is_not_object); |
| 2442 | 2440 |
| 2443 __ cmp(input, isolate()->factory()->null_value()); | 2441 __ cmp(input, isolate()->factory()->null_value()); |
| 2444 __ j(equal, is_object); | 2442 __ j(equal, is_object); |
| 2445 | 2443 |
| 2446 __ mov(temp1, FieldOperand(input, HeapObject::kMapOffset)); | 2444 __ mov(temp1, FieldOperand(input, HeapObject::kMapOffset)); |
| (...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3067 Register result = ToRegister(instr->result()); | 3065 Register result = ToRegister(instr->result()); |
| 3068 if (access.IsInobject()) { | 3066 if (access.IsInobject()) { |
| 3069 __ mov(result, FieldOperand(object, offset)); | 3067 __ mov(result, FieldOperand(object, offset)); |
| 3070 } else { | 3068 } else { |
| 3071 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); | 3069 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); |
| 3072 __ mov(result, FieldOperand(result, offset)); | 3070 __ mov(result, FieldOperand(result, offset)); |
| 3073 } | 3071 } |
| 3074 } | 3072 } |
| 3075 | 3073 |
| 3076 | 3074 |
| 3077 void LCodeGen::EmitLoadFieldOrConstantFunction(Register result, | 3075 void LCodeGen::EmitLoadFieldOrConstant(Register result, |
| 3078 Register object, | 3076 Register object, |
| 3079 Handle<Map> type, | 3077 Handle<Map> type, |
| 3080 Handle<String> name, | 3078 Handle<String> name, |
| 3081 LEnvironment* env) { | 3079 LEnvironment* env) { |
| 3082 LookupResult lookup(isolate()); | 3080 LookupResult lookup(isolate()); |
| 3083 type->LookupDescriptor(NULL, *name, &lookup); | 3081 type->LookupDescriptor(NULL, *name, &lookup); |
| 3084 ASSERT(lookup.IsFound() || lookup.IsCacheable()); | 3082 ASSERT(lookup.IsFound() || lookup.IsCacheable()); |
| 3085 if (lookup.IsField()) { | 3083 if (lookup.IsField()) { |
| 3086 int index = lookup.GetLocalFieldIndexFromMap(*type); | 3084 int index = lookup.GetLocalFieldIndexFromMap(*type); |
| 3087 int offset = index * kPointerSize; | 3085 int offset = index * kPointerSize; |
| 3088 if (index < 0) { | 3086 if (index < 0) { |
| 3089 // Negative property indices are in-object properties, indexed | 3087 // Negative property indices are in-object properties, indexed |
| 3090 // from the end of the fixed part of the object. | 3088 // from the end of the fixed part of the object. |
| 3091 __ mov(result, FieldOperand(object, offset + type->instance_size())); | 3089 __ mov(result, FieldOperand(object, offset + type->instance_size())); |
| 3092 } else { | 3090 } else { |
| 3093 // Non-negative property indices are in the properties array. | 3091 // Non-negative property indices are in the properties array. |
| 3094 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); | 3092 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); |
| 3095 __ mov(result, FieldOperand(result, offset + FixedArray::kHeaderSize)); | 3093 __ mov(result, FieldOperand(result, offset + FixedArray::kHeaderSize)); |
| 3096 } | 3094 } |
| 3097 } else if (lookup.IsConstantFunction()) { | 3095 } else if (lookup.IsConstant()) { |
| 3098 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*type)); | 3096 Handle<Object> constant(lookup.GetConstantFromMap(*type), isolate()); |
| 3099 __ LoadHeapObject(result, function); | 3097 __ LoadObject(result, constant); |
| 3100 } else { | 3098 } else { |
| 3101 // Negative lookup. | 3099 // Negative lookup. |
| 3102 // Check prototypes. | 3100 // Check prototypes. |
| 3103 Handle<HeapObject> current(HeapObject::cast((*type)->prototype())); | 3101 Handle<HeapObject> current(HeapObject::cast((*type)->prototype())); |
| 3104 Heap* heap = type->GetHeap(); | 3102 Heap* heap = type->GetHeap(); |
| 3105 while (*current != heap->null_value()) { | 3103 while (*current != heap->null_value()) { |
| 3106 __ LoadHeapObject(result, current); | 3104 __ LoadHeapObject(result, current); |
| 3107 __ cmp(FieldOperand(result, HeapObject::kMapOffset), | 3105 __ cmp(FieldOperand(result, HeapObject::kMapOffset), |
| 3108 Handle<Map>(current->map())); | 3106 Handle<Map>(current->map())); |
| 3109 DeoptimizeIf(not_equal, env); | 3107 DeoptimizeIf(not_equal, env); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 3138 static bool CompactEmit(SmallMapList* list, | 3136 static bool CompactEmit(SmallMapList* list, |
| 3139 Handle<String> name, | 3137 Handle<String> name, |
| 3140 int i, | 3138 int i, |
| 3141 Isolate* isolate) { | 3139 Isolate* isolate) { |
| 3142 Handle<Map> map = list->at(i); | 3140 Handle<Map> map = list->at(i); |
| 3143 // If the map has ElementsKind transitions, we will generate map checks | 3141 // If the map has ElementsKind transitions, we will generate map checks |
| 3144 // for each kind in __ CompareMap(..., ALLOW_ELEMENTS_TRANSITION_MAPS). | 3142 // for each kind in __ CompareMap(..., ALLOW_ELEMENTS_TRANSITION_MAPS). |
| 3145 if (map->HasElementsTransition()) return false; | 3143 if (map->HasElementsTransition()) return false; |
| 3146 LookupResult lookup(isolate); | 3144 LookupResult lookup(isolate); |
| 3147 map->LookupDescriptor(NULL, *name, &lookup); | 3145 map->LookupDescriptor(NULL, *name, &lookup); |
| 3148 return lookup.IsField() || lookup.IsConstantFunction(); | 3146 return lookup.IsField() || lookup.IsConstant(); |
| 3149 } | 3147 } |
| 3150 | 3148 |
| 3151 | 3149 |
| 3152 void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { | 3150 void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { |
| 3153 Register object = ToRegister(instr->object()); | 3151 Register object = ToRegister(instr->object()); |
| 3154 Register result = ToRegister(instr->result()); | 3152 Register result = ToRegister(instr->result()); |
| 3155 | 3153 |
| 3156 int map_count = instr->hydrogen()->types()->length(); | 3154 int map_count = instr->hydrogen()->types()->length(); |
| 3157 bool need_generic = instr->hydrogen()->need_generic(); | 3155 bool need_generic = instr->hydrogen()->need_generic(); |
| 3158 | 3156 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3170 } | 3168 } |
| 3171 } | 3169 } |
| 3172 for (int i = 0; i < map_count; ++i) { | 3170 for (int i = 0; i < map_count; ++i) { |
| 3173 bool last = (i == map_count - 1); | 3171 bool last = (i == map_count - 1); |
| 3174 Handle<Map> map = instr->hydrogen()->types()->at(i); | 3172 Handle<Map> map = instr->hydrogen()->types()->at(i); |
| 3175 Label check_passed; | 3173 Label check_passed; |
| 3176 __ CompareMap(object, map, &check_passed); | 3174 __ CompareMap(object, map, &check_passed); |
| 3177 if (last && !need_generic) { | 3175 if (last && !need_generic) { |
| 3178 DeoptimizeIf(not_equal, instr->environment()); | 3176 DeoptimizeIf(not_equal, instr->environment()); |
| 3179 __ bind(&check_passed); | 3177 __ bind(&check_passed); |
| 3180 EmitLoadFieldOrConstantFunction( | 3178 EmitLoadFieldOrConstant(result, object, map, name, instr->environment()); |
| 3181 result, object, map, name, instr->environment()); | |
| 3182 } else { | 3179 } else { |
| 3183 Label next; | 3180 Label next; |
| 3184 bool compact = all_are_compact ? true : | 3181 bool compact = all_are_compact ? true : |
| 3185 CompactEmit(instr->hydrogen()->types(), name, i, isolate()); | 3182 CompactEmit(instr->hydrogen()->types(), name, i, isolate()); |
| 3186 __ j(not_equal, &next, compact ? Label::kNear : Label::kFar); | 3183 __ j(not_equal, &next, compact ? Label::kNear : Label::kFar); |
| 3187 __ bind(&check_passed); | 3184 __ bind(&check_passed); |
| 3188 EmitLoadFieldOrConstantFunction( | 3185 EmitLoadFieldOrConstant(result, object, map, name, instr->environment()); |
| 3189 result, object, map, name, instr->environment()); | |
| 3190 __ jmp(&done, all_are_compact ? Label::kNear : Label::kFar); | 3186 __ jmp(&done, all_are_compact ? Label::kNear : Label::kFar); |
| 3191 __ bind(&next); | 3187 __ bind(&next); |
| 3192 } | 3188 } |
| 3193 } | 3189 } |
| 3194 if (need_generic) { | 3190 if (need_generic) { |
| 3195 __ mov(ecx, name); | 3191 __ mov(ecx, name); |
| 3196 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 3192 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 3197 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3193 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 3198 } | 3194 } |
| 3199 __ bind(&done); | 3195 __ bind(&done); |
| (...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3729 EDI_UNINITIALIZED); | 3725 EDI_UNINITIALIZED); |
| 3730 } | 3726 } |
| 3731 | 3727 |
| 3732 | 3728 |
| 3733 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { | 3729 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
| 3734 Register input_reg = ToRegister(instr->value()); | 3730 Register input_reg = ToRegister(instr->value()); |
| 3735 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 3731 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 3736 factory()->heap_number_map()); | 3732 factory()->heap_number_map()); |
| 3737 DeoptimizeIf(not_equal, instr->environment()); | 3733 DeoptimizeIf(not_equal, instr->environment()); |
| 3738 | 3734 |
| 3739 Label done; | 3735 Label slow, allocated, done; |
| 3740 Register tmp = input_reg.is(eax) ? ecx : eax; | 3736 Register tmp = input_reg.is(eax) ? ecx : eax; |
| 3741 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; | 3737 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; |
| 3742 | 3738 |
| 3743 // Preserve the value of all registers. | 3739 // Preserve the value of all registers. |
| 3744 PushSafepointRegistersScope scope(this); | 3740 PushSafepointRegistersScope scope(this); |
| 3745 | 3741 |
| 3746 Label negative; | |
| 3747 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); | 3742 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); |
| 3748 // Check the sign of the argument. If the argument is positive, just | 3743 // Check the sign of the argument. If the argument is positive, just |
| 3749 // return it. We do not need to patch the stack since |input| and | 3744 // return it. We do not need to patch the stack since |input| and |
| 3750 // |result| are the same register and |input| will be restored | 3745 // |result| are the same register and |input| will be restored |
| 3751 // unchanged by popping safepoint registers. | 3746 // unchanged by popping safepoint registers. |
| 3752 __ test(tmp, Immediate(HeapNumber::kSignMask)); | 3747 __ test(tmp, Immediate(HeapNumber::kSignMask)); |
| 3753 __ j(not_zero, &negative); | 3748 __ j(zero, &done); |
| 3754 __ jmp(&done); | |
| 3755 | 3749 |
| 3756 __ bind(&negative); | |
| 3757 | |
| 3758 Label allocated, slow; | |
| 3759 __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow); | 3750 __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow); |
| 3760 __ jmp(&allocated); | 3751 __ jmp(&allocated, Label::kNear); |
| 3761 | 3752 |
| 3762 // Slow case: Call the runtime system to do the number allocation. | 3753 // Slow case: Call the runtime system to do the number allocation. |
| 3763 __ bind(&slow); | 3754 __ bind(&slow); |
| 3764 | |
| 3765 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, | 3755 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, |
| 3766 instr, instr->context()); | 3756 instr, instr->context()); |
| 3767 | |
| 3768 // Set the pointer to the new heap number in tmp. | 3757 // Set the pointer to the new heap number in tmp. |
| 3769 if (!tmp.is(eax)) __ mov(tmp, eax); | 3758 if (!tmp.is(eax)) __ mov(tmp, eax); |
| 3770 | |
| 3771 // Restore input_reg after call to runtime. | 3759 // Restore input_reg after call to runtime. |
| 3772 __ LoadFromSafepointRegisterSlot(input_reg, input_reg); | 3760 __ LoadFromSafepointRegisterSlot(input_reg, input_reg); |
| 3773 | 3761 |
| 3774 __ bind(&allocated); | 3762 __ bind(&allocated); |
| 3775 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset)); | 3763 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset)); |
| 3776 __ and_(tmp2, ~HeapNumber::kSignMask); | 3764 __ and_(tmp2, ~HeapNumber::kSignMask); |
| 3777 __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2); | 3765 __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2); |
| 3778 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); | 3766 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); |
| 3779 __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2); | 3767 __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2); |
| 3780 __ StoreToSafepointRegisterSlot(input_reg, tmp); | 3768 __ StoreToSafepointRegisterSlot(input_reg, tmp); |
| 3781 | 3769 |
| 3782 __ bind(&done); | 3770 __ bind(&done); |
| 3783 } | 3771 } |
| 3784 | 3772 |
| 3785 | 3773 |
| 3786 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { | 3774 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { |
| 3787 Register input_reg = ToRegister(instr->value()); | 3775 Register input_reg = ToRegister(instr->value()); |
| 3788 __ test(input_reg, Operand(input_reg)); | 3776 __ test(input_reg, Operand(input_reg)); |
| 3789 Label is_positive; | 3777 Label is_positive; |
| 3790 __ j(not_sign, &is_positive); | 3778 __ j(not_sign, &is_positive, Label::kNear); |
| 3791 __ neg(input_reg); | 3779 __ neg(input_reg); // Sets flags. |
| 3792 __ test(input_reg, Operand(input_reg)); | |
| 3793 DeoptimizeIf(negative, instr->environment()); | 3780 DeoptimizeIf(negative, instr->environment()); |
| 3794 __ bind(&is_positive); | 3781 __ bind(&is_positive); |
| 3795 } | 3782 } |
| 3796 | 3783 |
| 3797 | 3784 |
| 3798 void LCodeGen::DoMathAbs(LMathAbs* instr) { | 3785 void LCodeGen::DoMathAbs(LMathAbs* instr) { |
| 3799 // Class for deferred case. | 3786 // Class for deferred case. |
| 3800 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 3787 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { |
| 3801 public: | 3788 public: |
| 3802 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) | 3789 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) |
| (...skipping 644 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4447 ASSERT(ToRegister(instr->value()).is(eax)); | 4434 ASSERT(ToRegister(instr->value()).is(eax)); |
| 4448 | 4435 |
| 4449 __ mov(ecx, instr->name()); | 4436 __ mov(ecx, instr->name()); |
| 4450 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 4437 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
| 4451 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 4438 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 4452 : isolate()->builtins()->StoreIC_Initialize(); | 4439 : isolate()->builtins()->StoreIC_Initialize(); |
| 4453 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 4440 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 4454 } | 4441 } |
| 4455 | 4442 |
| 4456 | 4443 |
| 4444 void LCodeGen::ApplyCheckIf(Condition cc, LBoundsCheck* check) { |
| 4445 if (FLAG_debug_code && check->hydrogen()->skip_check()) { |
| 4446 Label done; |
| 4447 __ j(NegateCondition(cc), &done, Label::kNear); |
| 4448 __ int3(); |
| 4449 __ bind(&done); |
| 4450 } else { |
| 4451 DeoptimizeIf(cc, check->environment()); |
| 4452 } |
| 4453 } |
| 4454 |
| 4455 |
| 4457 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { | 4456 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
| 4458 if (instr->hydrogen()->skip_check()) return; | 4457 if (instr->hydrogen()->skip_check() && !FLAG_debug_code) return; |
| 4459 | 4458 |
| 4460 if (instr->index()->IsConstantOperand()) { | 4459 if (instr->index()->IsConstantOperand()) { |
| 4461 int constant_index = | 4460 Immediate immediate = |
| 4462 ToInteger32(LConstantOperand::cast(instr->index())); | 4461 ToImmediate(LConstantOperand::cast(instr->index()), |
| 4463 if (instr->hydrogen()->length()->representation().IsSmi()) { | 4462 instr->hydrogen()->length()->representation()); |
| 4464 __ cmp(ToOperand(instr->length()), | 4463 __ cmp(ToOperand(instr->length()), immediate); |
| 4465 Immediate(Smi::FromInt(constant_index))); | 4464 Condition condition = |
| 4466 } else { | 4465 instr->hydrogen()->allow_equality() ? below : below_equal; |
| 4467 __ cmp(ToOperand(instr->length()), Immediate(constant_index)); | 4466 ApplyCheckIf(condition, instr); |
| 4468 } | |
| 4469 DeoptimizeIf(below_equal, instr->environment()); | |
| 4470 } else { | 4467 } else { |
| 4471 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); | 4468 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); |
| 4472 DeoptimizeIf(above_equal, instr->environment()); | 4469 Condition condition = |
| 4470 instr->hydrogen()->allow_equality() ? above : above_equal; |
| 4471 ApplyCheckIf(condition, instr); |
| 4473 } | 4472 } |
| 4474 } | 4473 } |
| 4475 | 4474 |
| 4476 | 4475 |
| 4477 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { | 4476 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { |
| 4478 ElementsKind elements_kind = instr->elements_kind(); | 4477 ElementsKind elements_kind = instr->elements_kind(); |
| 4479 LOperand* key = instr->key(); | 4478 LOperand* key = instr->key(); |
| 4480 if (!key->IsConstantOperand() && | 4479 if (!key->IsConstantOperand() && |
| 4481 ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(), | 4480 ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(), |
| 4482 elements_kind)) { | 4481 elements_kind)) { |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4622 instr->elements(), | 4621 instr->elements(), |
| 4623 instr->key(), | 4622 instr->key(), |
| 4624 instr->hydrogen()->key()->representation(), | 4623 instr->hydrogen()->key()->representation(), |
| 4625 FAST_ELEMENTS, | 4624 FAST_ELEMENTS, |
| 4626 FixedArray::kHeaderSize - kHeapObjectTag, | 4625 FixedArray::kHeaderSize - kHeapObjectTag, |
| 4627 instr->additional_index()); | 4626 instr->additional_index()); |
| 4628 if (instr->value()->IsRegister()) { | 4627 if (instr->value()->IsRegister()) { |
| 4629 __ mov(operand, ToRegister(instr->value())); | 4628 __ mov(operand, ToRegister(instr->value())); |
| 4630 } else { | 4629 } else { |
| 4631 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); | 4630 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
| 4632 if (IsInteger32(operand_value)) { | 4631 if (IsSmi(operand_value)) { |
| 4633 Smi* smi_value = Smi::FromInt(ToInteger32(operand_value)); | 4632 Immediate immediate = ToImmediate(operand_value, Representation::Smi()); |
| 4634 __ mov(operand, Immediate(smi_value)); | 4633 __ mov(operand, immediate); |
| 4635 } else { | 4634 } else { |
| 4635 ASSERT(!IsInteger32(operand_value)); |
| 4636 Handle<Object> handle_value = ToHandle(operand_value); | 4636 Handle<Object> handle_value = ToHandle(operand_value); |
| 4637 __ mov(operand, handle_value); | 4637 __ mov(operand, handle_value); |
| 4638 } | 4638 } |
| 4639 } | 4639 } |
| 4640 | 4640 |
| 4641 if (instr->hydrogen()->NeedsWriteBarrier()) { | 4641 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 4642 ASSERT(instr->value()->IsRegister()); | 4642 ASSERT(instr->value()->IsRegister()); |
| 4643 Register value = ToRegister(instr->value()); | 4643 Register value = ToRegister(instr->value()); |
| 4644 ASSERT(!instr->key()->IsConstantOperand()); | 4644 ASSERT(!instr->key()->IsConstantOperand()); |
| 4645 SmiCheck check_needed = | 4645 SmiCheck check_needed = |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4708 if (is_simple_map_transition) { | 4708 if (is_simple_map_transition) { |
| 4709 Register new_map_reg = ToRegister(instr->new_map_temp()); | 4709 Register new_map_reg = ToRegister(instr->new_map_temp()); |
| 4710 Handle<Map> map = instr->hydrogen()->transitioned_map(); | 4710 Handle<Map> map = instr->hydrogen()->transitioned_map(); |
| 4711 __ mov(FieldOperand(object_reg, HeapObject::kMapOffset), | 4711 __ mov(FieldOperand(object_reg, HeapObject::kMapOffset), |
| 4712 Immediate(map)); | 4712 Immediate(map)); |
| 4713 // Write barrier. | 4713 // Write barrier. |
| 4714 ASSERT_NE(instr->temp(), NULL); | 4714 ASSERT_NE(instr->temp(), NULL); |
| 4715 __ RecordWriteForMap(object_reg, to_map, new_map_reg, | 4715 __ RecordWriteForMap(object_reg, to_map, new_map_reg, |
| 4716 ToRegister(instr->temp()), | 4716 ToRegister(instr->temp()), |
| 4717 kDontSaveFPRegs); | 4717 kDontSaveFPRegs); |
| 4718 } else if (FLAG_compiled_transitions) { | 4718 } else { |
| 4719 PushSafepointRegistersScope scope(this); | 4719 PushSafepointRegistersScope scope(this); |
| 4720 if (!object_reg.is(eax)) { | 4720 if (!object_reg.is(eax)) { |
| 4721 __ push(object_reg); | 4721 __ push(object_reg); |
| 4722 } | 4722 } |
| 4723 LoadContextFromDeferred(instr->context()); | 4723 LoadContextFromDeferred(instr->context()); |
| 4724 if (!object_reg.is(eax)) { | 4724 if (!object_reg.is(eax)) { |
| 4725 __ pop(eax); | 4725 __ pop(eax); |
| 4726 } | 4726 } |
| 4727 __ mov(ebx, to_map); | 4727 __ mov(ebx, to_map); |
| 4728 TransitionElementsKindStub stub(from_kind, to_kind); | 4728 TransitionElementsKindStub stub(from_kind, to_kind); |
| 4729 __ CallStub(&stub); | 4729 __ CallStub(&stub); |
| 4730 RecordSafepointWithRegisters( | 4730 RecordSafepointWithRegisters( |
| 4731 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 4731 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
| 4732 } else if (IsFastSmiElementsKind(from_kind) && | |
| 4733 IsFastDoubleElementsKind(to_kind)) { | |
| 4734 Register new_map_reg = ToRegister(instr->new_map_temp()); | |
| 4735 __ mov(new_map_reg, to_map); | |
| 4736 Register fixed_object_reg = ToRegister(instr->temp()); | |
| 4737 ASSERT(fixed_object_reg.is(edx)); | |
| 4738 ASSERT(new_map_reg.is(ebx)); | |
| 4739 __ mov(fixed_object_reg, object_reg); | |
| 4740 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), | |
| 4741 RelocInfo::CODE_TARGET, instr); | |
| 4742 } else if (IsFastDoubleElementsKind(from_kind) && | |
| 4743 IsFastObjectElementsKind(to_kind)) { | |
| 4744 Register new_map_reg = ToRegister(instr->new_map_temp()); | |
| 4745 __ mov(new_map_reg, to_map); | |
| 4746 Register fixed_object_reg = ToRegister(instr->temp()); | |
| 4747 ASSERT(fixed_object_reg.is(edx)); | |
| 4748 ASSERT(new_map_reg.is(ebx)); | |
| 4749 __ mov(fixed_object_reg, object_reg); | |
| 4750 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), | |
| 4751 RelocInfo::CODE_TARGET, instr); | |
| 4752 } else { | |
| 4753 UNREACHABLE(); | |
| 4754 } | 4732 } |
| 4755 __ bind(¬_applicable); | 4733 __ bind(¬_applicable); |
| 4756 } | 4734 } |
| 4757 | 4735 |
| 4758 | 4736 |
| 4759 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { | 4737 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { |
| 4760 class DeferredStringCharCodeAt: public LDeferredCode { | 4738 class DeferredStringCharCodeAt: public LDeferredCode { |
| 4761 public: | 4739 public: |
| 4762 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) | 4740 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) |
| 4763 : LDeferredCode(codegen), instr_(instr) { } | 4741 : LDeferredCode(codegen), instr_(instr) { } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 4788 // result register contain a valid pointer because it is already | 4766 // result register contain a valid pointer because it is already |
| 4789 // contained in the register pointer map. | 4767 // contained in the register pointer map. |
| 4790 __ Set(result, Immediate(0)); | 4768 __ Set(result, Immediate(0)); |
| 4791 | 4769 |
| 4792 PushSafepointRegistersScope scope(this); | 4770 PushSafepointRegistersScope scope(this); |
| 4793 __ push(string); | 4771 __ push(string); |
| 4794 // Push the index as a smi. This is safe because of the checks in | 4772 // Push the index as a smi. This is safe because of the checks in |
| 4795 // DoStringCharCodeAt above. | 4773 // DoStringCharCodeAt above. |
| 4796 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); | 4774 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); |
| 4797 if (instr->index()->IsConstantOperand()) { | 4775 if (instr->index()->IsConstantOperand()) { |
| 4798 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 4776 Immediate immediate = ToImmediate(LConstantOperand::cast(instr->index()), |
| 4799 __ push(Immediate(Smi::FromInt(const_index))); | 4777 Representation::Smi()); |
| 4778 __ push(immediate); |
| 4800 } else { | 4779 } else { |
| 4801 Register index = ToRegister(instr->index()); | 4780 Register index = ToRegister(instr->index()); |
| 4802 __ SmiTag(index); | 4781 __ SmiTag(index); |
| 4803 __ push(index); | 4782 __ push(index); |
| 4804 } | 4783 } |
| 4805 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, | 4784 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, |
| 4806 instr, instr->context()); | 4785 instr, instr->context()); |
| 4807 __ AssertSmi(eax); | 4786 __ AssertSmi(eax); |
| 4808 __ SmiUntag(eax); | 4787 __ SmiUntag(eax); |
| 4809 __ StoreToSafepointRegisterSlot(result, eax); | 4788 __ StoreToSafepointRegisterSlot(result, eax); |
| (...skipping 985 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5795 Handle<Map> map, | 5774 Handle<Map> map, |
| 5796 LInstruction* instr) { | 5775 LInstruction* instr) { |
| 5797 Label success; | 5776 Label success; |
| 5798 __ CompareMap(reg, map, &success); | 5777 __ CompareMap(reg, map, &success); |
| 5799 DeoptimizeIf(not_equal, instr->environment()); | 5778 DeoptimizeIf(not_equal, instr->environment()); |
| 5800 __ bind(&success); | 5779 __ bind(&success); |
| 5801 } | 5780 } |
| 5802 | 5781 |
| 5803 | 5782 |
| 5804 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 5783 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
| 5784 if (instr->hydrogen()->CanOmitMapChecks()) return; |
| 5805 LOperand* input = instr->value(); | 5785 LOperand* input = instr->value(); |
| 5806 ASSERT(input->IsRegister()); | 5786 ASSERT(input->IsRegister()); |
| 5807 Register reg = ToRegister(input); | 5787 Register reg = ToRegister(input); |
| 5808 | 5788 |
| 5809 Label success; | 5789 Label success; |
| 5810 SmallMapList* map_set = instr->hydrogen()->map_set(); | 5790 SmallMapList* map_set = instr->hydrogen()->map_set(); |
| 5811 for (int i = 0; i < map_set->length() - 1; i++) { | 5791 for (int i = 0; i < map_set->length() - 1; i++) { |
| 5812 Handle<Map> map = map_set->at(i); | 5792 Handle<Map> map = map_set->at(i); |
| 5813 __ CompareMap(reg, map, &success); | 5793 __ CompareMap(reg, map, &success); |
| 5814 __ j(equal, &success); | 5794 __ j(equal, &success); |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5985 if (!input_reg.is(result_reg)) { | 5965 if (!input_reg.is(result_reg)) { |
| 5986 __ mov(result_reg, input_reg); | 5966 __ mov(result_reg, input_reg); |
| 5987 } | 5967 } |
| 5988 __ SmiUntag(result_reg); | 5968 __ SmiUntag(result_reg); |
| 5989 __ ClampUint8(result_reg); | 5969 __ ClampUint8(result_reg); |
| 5990 __ bind(&done); | 5970 __ bind(&done); |
| 5991 } | 5971 } |
| 5992 | 5972 |
| 5993 | 5973 |
| 5994 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { | 5974 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { |
| 5975 if (instr->hydrogen()->CanOmitPrototypeChecks()) return; |
| 5995 Register reg = ToRegister(instr->temp()); | 5976 Register reg = ToRegister(instr->temp()); |
| 5996 | 5977 |
| 5997 ZoneList<Handle<JSObject> >* prototypes = instr->prototypes(); | 5978 ZoneList<Handle<JSObject> >* prototypes = instr->prototypes(); |
| 5998 ZoneList<Handle<Map> >* maps = instr->maps(); | 5979 ZoneList<Handle<Map> >* maps = instr->maps(); |
| 5999 | 5980 |
| 6000 ASSERT(prototypes->length() == maps->length()); | 5981 ASSERT(prototypes->length() == maps->length()); |
| 6001 | 5982 |
| 6002 if (!instr->hydrogen()->CanOmitPrototypeChecks()) { | 5983 for (int i = 0; i < prototypes->length(); i++) { |
| 6003 for (int i = 0; i < prototypes->length(); i++) { | 5984 __ LoadHeapObject(reg, prototypes->at(i)); |
| 6004 __ LoadHeapObject(reg, prototypes->at(i)); | 5985 DoCheckMapCommon(reg, maps->at(i), instr); |
| 6005 DoCheckMapCommon(reg, maps->at(i), instr); | |
| 6006 } | |
| 6007 } | 5986 } |
| 6008 } | 5987 } |
| 6009 | 5988 |
| 6010 | 5989 |
| 6011 void LCodeGen::DoAllocate(LAllocate* instr) { | 5990 void LCodeGen::DoAllocate(LAllocate* instr) { |
| 6012 class DeferredAllocate: public LDeferredCode { | 5991 class DeferredAllocate: public LDeferredCode { |
| 6013 public: | 5992 public: |
| 6014 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) | 5993 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) |
| 6015 : LDeferredCode(codegen), instr_(instr) { } | 5994 : LDeferredCode(codegen), instr_(instr) { } |
| 6016 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); } | 5995 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); } |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6316 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { | 6295 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { |
| 6317 EnsureSpaceForLazyDeopt(); | 6296 EnsureSpaceForLazyDeopt(); |
| 6318 ASSERT(instr->HasEnvironment()); | 6297 ASSERT(instr->HasEnvironment()); |
| 6319 LEnvironment* env = instr->environment(); | 6298 LEnvironment* env = instr->environment(); |
| 6320 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 6299 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
| 6321 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 6300 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
| 6322 } | 6301 } |
| 6323 | 6302 |
| 6324 | 6303 |
| 6325 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { | 6304 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { |
| 6326 if (instr->hydrogen_value()->IsSoftDeoptimize()) { | 6305 Deoptimizer::BailoutType type = instr->hydrogen()->type(); |
| 6327 SoftDeoptimize(instr->environment()); | 6306 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the |
| 6328 } else { | 6307 // needed return address), even though the implementation of LAZY and EAGER is |
| 6329 DeoptimizeIf(no_condition, instr->environment()); | 6308 // now identical. When LAZY is eventually completely folded into EAGER, remove |
| 6309 // the special case below. |
| 6310 if (info()->IsStub() && type == Deoptimizer::EAGER) { |
| 6311 type = Deoptimizer::LAZY; |
| 6330 } | 6312 } |
| 6313 DeoptimizeIf(no_condition, instr->environment(), type); |
| 6331 } | 6314 } |
| 6332 | 6315 |
| 6333 | 6316 |
| 6334 void LCodeGen::DoDummyUse(LDummyUse* instr) { | 6317 void LCodeGen::DoDummyUse(LDummyUse* instr) { |
| 6335 // Nothing to see here, move on! | 6318 // Nothing to see here, move on! |
| 6336 } | 6319 } |
| 6337 | 6320 |
| 6338 | 6321 |
| 6339 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { | 6322 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { |
| 6340 PushSafepointRegistersScope scope(this); | 6323 PushSafepointRegistersScope scope(this); |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6501 FixedArray::kHeaderSize - kPointerSize)); | 6484 FixedArray::kHeaderSize - kPointerSize)); |
| 6502 __ bind(&done); | 6485 __ bind(&done); |
| 6503 } | 6486 } |
| 6504 | 6487 |
| 6505 | 6488 |
| 6506 #undef __ | 6489 #undef __ |
| 6507 | 6490 |
| 6508 } } // namespace v8::internal | 6491 } } // namespace v8::internal |
| 6509 | 6492 |
| 6510 #endif // V8_TARGET_ARCH_IA32 | 6493 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |