OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 1676 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1687 Register reg = ToRegister(instr->input()); | 1687 Register reg = ToRegister(instr->input()); |
1688 int true_block = instr->true_block_id(); | 1688 int true_block = instr->true_block_id(); |
1689 int false_block = instr->false_block_id(); | 1689 int false_block = instr->false_block_id(); |
1690 | 1690 |
1691 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); | 1691 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); |
1692 EmitBranch(true_block, false_block, equal); | 1692 EmitBranch(true_block, false_block, equal); |
1693 } | 1693 } |
1694 | 1694 |
1695 | 1695 |
1696 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 1696 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
1697 // Object and function are in fixed registers eax and edx. | 1697 // Object and function are in fixed registers defined by the stub. |
1698 InstanceofStub stub(InstanceofStub::kArgsInRegisters); | 1698 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
1699 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1699 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
1700 | 1700 |
1701 NearLabel true_value, done; | 1701 NearLabel true_value, done; |
1702 __ test(eax, Operand(eax)); | 1702 __ test(eax, Operand(eax)); |
1703 __ j(zero, &true_value); | 1703 __ j(zero, &true_value); |
1704 __ mov(ToRegister(instr->result()), Factory::false_value()); | 1704 __ mov(ToRegister(instr->result()), Factory::false_value()); |
1705 __ jmp(&done); | 1705 __ jmp(&done); |
1706 __ bind(&true_value); | 1706 __ bind(&true_value); |
1707 __ mov(ToRegister(instr->result()), Factory::true_value()); | 1707 __ mov(ToRegister(instr->result()), Factory::true_value()); |
1708 __ bind(&done); | 1708 __ bind(&done); |
1709 } | 1709 } |
1710 | 1710 |
1711 | 1711 |
1712 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { | 1712 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { |
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()); |
1715 | 1715 |
1716 InstanceofStub stub(InstanceofStub::kArgsInRegisters); | 1716 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
1717 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1717 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
1718 __ test(eax, Operand(eax)); | 1718 __ test(eax, Operand(eax)); |
1719 EmitBranch(true_block, false_block, zero); | 1719 EmitBranch(true_block, false_block, zero); |
1720 } | 1720 } |
1721 | 1721 |
1722 | 1722 |
| 1723 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { |
| 1724 class DeferredInstanceOfKnownGlobal: public LDeferredCode { |
| 1725 public: |
| 1726 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, |
| 1727 LInstanceOfKnownGlobal* instr) |
| 1728 : LDeferredCode(codegen), instr_(instr) { } |
| 1729 virtual void Generate() { |
| 1730 codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_); |
| 1731 } |
| 1732 |
| 1733 Label* map_check() { return &map_check_; } |
| 1734 |
| 1735 private: |
| 1736 LInstanceOfKnownGlobal* instr_; |
| 1737 Label map_check_; |
| 1738 }; |
| 1739 |
| 1740 DeferredInstanceOfKnownGlobal* deferred; |
| 1741 deferred = new DeferredInstanceOfKnownGlobal(this, instr); |
| 1742 |
| 1743 Label done, false_result; |
| 1744 Register object = ToRegister(instr->input()); |
| 1745 Register temp = ToRegister(instr->temp()); |
| 1746 |
| 1747 // A Smi is not instance of anything. |
| 1748 __ test(object, Immediate(kSmiTagMask)); |
| 1749 __ j(zero, &false_result, not_taken); |
| 1750 |
| 1751 // This is the inlined call site instanceof cache. The two occourences of the |
| 1752 // hole value will be patched to the last map/result pair generated by the |
| 1753 // instanceof stub. |
| 1754 NearLabel cache_miss; |
| 1755 Register map = ToRegister(instr->temp()); |
| 1756 __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); |
| 1757 __ bind(deferred->map_check()); // Label for calculating code patching. |
| 1758 __ cmp(map, Factory::the_hole_value()); // Patched to cached map. |
| 1759 __ j(not_equal, &cache_miss, not_taken); |
| 1760 __ mov(eax, Factory::the_hole_value()); // Patched to either true or false. |
| 1761 __ jmp(&done); |
| 1762 |
| 1763 // The inlined call site cache did not match. Check null and string before |
| 1764 // calling the deferred code. |
| 1765 __ bind(&cache_miss); |
| 1766 // Null is not instance of anything. |
| 1767 __ cmp(object, Factory::null_value()); |
| 1768 __ j(equal, &false_result); |
| 1769 |
| 1770 // String values are not instances of anything. |
| 1771 Condition is_string = masm_->IsObjectStringType(object, temp, temp); |
| 1772 __ j(is_string, &false_result); |
| 1773 |
| 1774 // Go to the deferred code. |
| 1775 __ jmp(deferred->entry()); |
| 1776 |
| 1777 __ bind(&false_result); |
| 1778 __ mov(ToRegister(instr->result()), Factory::false_value()); |
| 1779 |
| 1780 // Here result has either true or false. Deferred code also produces true or |
| 1781 // false object. |
| 1782 __ bind(deferred->exit()); |
| 1783 __ bind(&done); |
| 1784 } |
| 1785 |
| 1786 |
| 1787 void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, |
| 1788 Label* map_check) { |
| 1789 __ PushSafepointRegisters(); |
| 1790 |
| 1791 InstanceofStub::Flags flags = InstanceofStub::kNoFlags; |
| 1792 flags = static_cast<InstanceofStub::Flags>( |
| 1793 flags | InstanceofStub::kArgsInRegisters); |
| 1794 flags = static_cast<InstanceofStub::Flags>( |
| 1795 flags | InstanceofStub::kCallSiteInlineCheck); |
| 1796 flags = static_cast<InstanceofStub::Flags>( |
| 1797 flags | InstanceofStub::kReturnTrueFalseObject); |
| 1798 InstanceofStub stub(flags); |
| 1799 |
| 1800 // Get the temp register reserved by the instruction. This needs to be edi as |
| 1801 // its slot of the pushing of safepoint registers is used to communicate the |
| 1802 // offset to the location of the map check. |
| 1803 Register temp = ToRegister(instr->temp()); |
| 1804 ASSERT(temp.is(edi)); |
| 1805 __ mov(InstanceofStub::right(), Immediate(instr->function())); |
| 1806 static const int kAdditionalDelta = 13; |
| 1807 int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; |
| 1808 Label before_push_delta; |
| 1809 __ bind(&before_push_delta); |
| 1810 __ mov(temp, Immediate(delta)); |
| 1811 __ mov(Operand(esp, EspIndexForPushAll(temp) * kPointerSize), temp); |
| 1812 __ call(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 1813 ASSERT_EQ(kAdditionalDelta, |
| 1814 masm_->SizeOfCodeGeneratedSince(&before_push_delta)); |
| 1815 RecordSafepointWithRegisters( |
| 1816 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); |
| 1817 // Put the result value into the eax slot and restore all registers. |
| 1818 __ mov(Operand(esp, EspIndexForPushAll(eax) * kPointerSize), eax); |
| 1819 |
| 1820 __ PopSafepointRegisters(); |
| 1821 } |
| 1822 |
| 1823 |
1723 static Condition ComputeCompareCondition(Token::Value op) { | 1824 static Condition ComputeCompareCondition(Token::Value op) { |
1724 switch (op) { | 1825 switch (op) { |
1725 case Token::EQ_STRICT: | 1826 case Token::EQ_STRICT: |
1726 case Token::EQ: | 1827 case Token::EQ: |
1727 return equal; | 1828 return equal; |
1728 case Token::LT: | 1829 case Token::LT: |
1729 return less; | 1830 return less; |
1730 case Token::GT: | 1831 case Token::GT: |
1731 return greater; | 1832 return greater; |
1732 case Token::LTE: | 1833 case Token::LTE: |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1892 | 1993 |
1893 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { | 1994 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
1894 Register arguments = ToRegister(instr->arguments()); | 1995 Register arguments = ToRegister(instr->arguments()); |
1895 Register length = ToRegister(instr->length()); | 1996 Register length = ToRegister(instr->length()); |
1896 Operand index = ToOperand(instr->index()); | 1997 Operand index = ToOperand(instr->index()); |
1897 Register result = ToRegister(instr->result()); | 1998 Register result = ToRegister(instr->result()); |
1898 | 1999 |
1899 __ sub(length, index); | 2000 __ sub(length, index); |
1900 DeoptimizeIf(below_equal, instr->environment()); | 2001 DeoptimizeIf(below_equal, instr->environment()); |
1901 | 2002 |
| 2003 // There are two words between the frame pointer and the last argument. |
| 2004 // Subtracting from length accounts for one of them add one more. |
1902 __ mov(result, Operand(arguments, length, times_4, kPointerSize)); | 2005 __ mov(result, Operand(arguments, length, times_4, kPointerSize)); |
1903 } | 2006 } |
1904 | 2007 |
1905 | 2008 |
1906 void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { | 2009 void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { |
1907 Register elements = ToRegister(instr->elements()); | 2010 Register elements = ToRegister(instr->elements()); |
1908 Register key = ToRegister(instr->key()); | 2011 Register key = ToRegister(instr->key()); |
1909 Register result; | 2012 Register result; |
1910 if (instr->load_result() != NULL) { | 2013 if (instr->load_result() != NULL) { |
1911 result = ToRegister(instr->load_result()); | 2014 result = ToRegister(instr->load_result()); |
(...skipping 29 matching lines...) Expand all Loading... |
1941 | 2044 |
1942 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 2045 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
1943 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2046 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
1944 } | 2047 } |
1945 | 2048 |
1946 | 2049 |
1947 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { | 2050 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
1948 Register result = ToRegister(instr->result()); | 2051 Register result = ToRegister(instr->result()); |
1949 | 2052 |
1950 // Check for arguments adapter frame. | 2053 // Check for arguments adapter frame. |
1951 Label done, adapted; | 2054 NearLabel done, adapted; |
1952 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 2055 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
1953 __ mov(result, Operand(result, StandardFrameConstants::kContextOffset)); | 2056 __ mov(result, Operand(result, StandardFrameConstants::kContextOffset)); |
1954 __ cmp(Operand(result), | 2057 __ cmp(Operand(result), |
1955 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 2058 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
1956 __ j(equal, &adapted); | 2059 __ j(equal, &adapted); |
1957 | 2060 |
1958 // No arguments adaptor frame. | 2061 // No arguments adaptor frame. |
1959 __ mov(result, Operand(ebp)); | 2062 __ mov(result, Operand(ebp)); |
1960 __ jmp(&done); | 2063 __ jmp(&done); |
1961 | 2064 |
1962 // Arguments adaptor frame present. | 2065 // Arguments adaptor frame present. |
1963 __ bind(&adapted); | 2066 __ bind(&adapted); |
1964 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 2067 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
1965 | 2068 |
1966 // Done. Pointer to topmost argument is in result. | 2069 // Result is the frame pointer for the frame if not adapted and for the real |
| 2070 // frame below the adaptor frame if adapted. |
1967 __ bind(&done); | 2071 __ bind(&done); |
1968 } | 2072 } |
1969 | 2073 |
1970 | 2074 |
1971 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { | 2075 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { |
1972 Operand elem = ToOperand(instr->input()); | 2076 Operand elem = ToOperand(instr->input()); |
1973 Register result = ToRegister(instr->result()); | 2077 Register result = ToRegister(instr->result()); |
1974 | 2078 |
1975 Label done; | 2079 NearLabel done; |
1976 | 2080 |
1977 // No arguments adaptor frame. Number of arguments is fixed. | 2081 // If no arguments adaptor frame the number of arguments is fixed. |
1978 __ cmp(ebp, elem); | 2082 __ cmp(ebp, elem); |
1979 __ mov(result, Immediate(scope()->num_parameters())); | 2083 __ mov(result, Immediate(scope()->num_parameters())); |
1980 __ j(equal, &done); | 2084 __ j(equal, &done); |
1981 | 2085 |
1982 // Arguments adaptor frame present. Get argument length from there. | 2086 // Arguments adaptor frame present. Get argument length from there. |
1983 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 2087 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
1984 __ mov(result, Operand(result, | 2088 __ mov(result, Operand(result, |
1985 ArgumentsAdaptorFrameConstants::kLengthOffset)); | 2089 ArgumentsAdaptorFrameConstants::kLengthOffset)); |
1986 __ SmiUntag(result); | 2090 __ SmiUntag(result); |
1987 | 2091 |
1988 // Done. Argument length is in result register. | 2092 // Argument length is in result register. |
1989 __ bind(&done); | 2093 __ bind(&done); |
1990 } | 2094 } |
1991 | 2095 |
1992 | 2096 |
1993 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { | 2097 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
1994 Register receiver = ToRegister(instr->receiver()); | 2098 Register receiver = ToRegister(instr->receiver()); |
1995 ASSERT(ToRegister(instr->function()).is(edi)); | 2099 ASSERT(ToRegister(instr->function()).is(edi)); |
1996 ASSERT(ToRegister(instr->result()).is(eax)); | 2100 ASSERT(ToRegister(instr->result()).is(eax)); |
1997 | 2101 |
1998 // If the receiver is null or undefined, we have to pass the | 2102 // If the receiver is null or undefined, we have to pass the |
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2527 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); | 2631 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
2528 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); | 2632 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); |
2529 int offset = | 2633 int offset = |
2530 ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize; | 2634 ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize; |
2531 __ mov(FieldOperand(elements, offset), value); | 2635 __ mov(FieldOperand(elements, offset), value); |
2532 } else { | 2636 } else { |
2533 __ mov(FieldOperand(elements, key, times_4, FixedArray::kHeaderSize), | 2637 __ mov(FieldOperand(elements, key, times_4, FixedArray::kHeaderSize), |
2534 value); | 2638 value); |
2535 } | 2639 } |
2536 | 2640 |
2537 // Update the write barrier unless we're certain that we're storing a smi. | |
2538 if (instr->hydrogen()->NeedsWriteBarrier()) { | 2641 if (instr->hydrogen()->NeedsWriteBarrier()) { |
2539 // Compute address of modified element and store it into key register. | 2642 // Compute address of modified element and store it into key register. |
2540 __ lea(key, FieldOperand(elements, key, times_4, FixedArray::kHeaderSize)); | 2643 __ lea(key, FieldOperand(elements, key, times_4, FixedArray::kHeaderSize)); |
2541 __ RecordWrite(elements, key, value); | 2644 __ RecordWrite(elements, key, value); |
2542 } | 2645 } |
2543 } | 2646 } |
2544 | 2647 |
2545 | 2648 |
2546 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 2649 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
2547 ASSERT(ToRegister(instr->object()).is(edx)); | 2650 ASSERT(ToRegister(instr->object()).is(edx)); |
(...skipping 752 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3300 ASSERT(!environment->HasBeenRegistered()); | 3403 ASSERT(!environment->HasBeenRegistered()); |
3301 RegisterEnvironmentForDeoptimization(environment); | 3404 RegisterEnvironmentForDeoptimization(environment); |
3302 ASSERT(osr_pc_offset_ == -1); | 3405 ASSERT(osr_pc_offset_ == -1); |
3303 osr_pc_offset_ = masm()->pc_offset(); | 3406 osr_pc_offset_ = masm()->pc_offset(); |
3304 } | 3407 } |
3305 | 3408 |
3306 | 3409 |
3307 #undef __ | 3410 #undef __ |
3308 | 3411 |
3309 } } // namespace v8::internal | 3412 } } // namespace v8::internal |
OLD | NEW |