OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 1843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1854 | 1854 |
1855 | 1855 |
1856 int LCodeGen::GetNextEmittedBlock() const { | 1856 int LCodeGen::GetNextEmittedBlock() const { |
1857 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { | 1857 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { |
1858 if (!chunk_->GetLabel(i)->HasReplacement()) return i; | 1858 if (!chunk_->GetLabel(i)->HasReplacement()) return i; |
1859 } | 1859 } |
1860 return -1; | 1860 return -1; |
1861 } | 1861 } |
1862 | 1862 |
1863 | 1863 |
1864 void LCodeGen::EmitBranch(int left_block, int right_block, Condition cc) { | 1864 template<class InstrType> |
| 1865 void LCodeGen::EmitBranch(InstrType instr, Condition cc) { |
| 1866 int right_block = instr->FalseDestination(chunk_); |
| 1867 int left_block = instr->TrueDestination(chunk_); |
| 1868 |
1865 int next_block = GetNextEmittedBlock(); | 1869 int next_block = GetNextEmittedBlock(); |
1866 right_block = chunk_->LookupDestination(right_block); | |
1867 left_block = chunk_->LookupDestination(left_block); | |
1868 | 1870 |
1869 if (right_block == left_block) { | 1871 if (right_block == left_block) { |
1870 EmitGoto(left_block); | 1872 EmitGoto(left_block); |
1871 } else if (left_block == next_block) { | 1873 } else if (left_block == next_block) { |
1872 __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block)); | 1874 __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block)); |
1873 } else if (right_block == next_block) { | 1875 } else if (right_block == next_block) { |
1874 __ j(cc, chunk_->GetAssemblyLabel(left_block)); | 1876 __ j(cc, chunk_->GetAssemblyLabel(left_block)); |
1875 } else { | 1877 } else { |
1876 __ j(cc, chunk_->GetAssemblyLabel(left_block)); | 1878 __ j(cc, chunk_->GetAssemblyLabel(left_block)); |
1877 if (cc != always) { | 1879 if (cc != always) { |
1878 __ jmp(chunk_->GetAssemblyLabel(right_block)); | 1880 __ jmp(chunk_->GetAssemblyLabel(right_block)); |
1879 } | 1881 } |
1880 } | 1882 } |
1881 } | 1883 } |
1882 | 1884 |
1883 | 1885 |
1884 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { | 1886 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { |
1885 __ int3(); | 1887 __ int3(); |
1886 } | 1888 } |
1887 | 1889 |
1888 | 1890 |
1889 void LCodeGen::DoBranch(LBranch* instr) { | 1891 void LCodeGen::DoBranch(LBranch* instr) { |
1890 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
1891 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
1892 | |
1893 Representation r = instr->hydrogen()->value()->representation(); | 1892 Representation r = instr->hydrogen()->value()->representation(); |
1894 if (r.IsInteger32()) { | 1893 if (r.IsInteger32()) { |
1895 ASSERT(!info()->IsStub()); | 1894 ASSERT(!info()->IsStub()); |
1896 Register reg = ToRegister(instr->value()); | 1895 Register reg = ToRegister(instr->value()); |
1897 __ testl(reg, reg); | 1896 __ testl(reg, reg); |
1898 EmitBranch(true_block, false_block, not_zero); | 1897 EmitBranch(instr, not_zero); |
1899 } else if (r.IsSmi()) { | 1898 } else if (r.IsSmi()) { |
1900 ASSERT(!info()->IsStub()); | 1899 ASSERT(!info()->IsStub()); |
1901 Register reg = ToRegister(instr->value()); | 1900 Register reg = ToRegister(instr->value()); |
1902 __ testq(reg, reg); | 1901 __ testq(reg, reg); |
1903 EmitBranch(true_block, false_block, not_zero); | 1902 EmitBranch(instr, not_zero); |
1904 } else if (r.IsDouble()) { | 1903 } else if (r.IsDouble()) { |
1905 ASSERT(!info()->IsStub()); | 1904 ASSERT(!info()->IsStub()); |
1906 XMMRegister reg = ToDoubleRegister(instr->value()); | 1905 XMMRegister reg = ToDoubleRegister(instr->value()); |
1907 __ xorps(xmm0, xmm0); | 1906 __ xorps(xmm0, xmm0); |
1908 __ ucomisd(reg, xmm0); | 1907 __ ucomisd(reg, xmm0); |
1909 EmitBranch(true_block, false_block, not_equal); | 1908 EmitBranch(instr, not_equal); |
1910 } else { | 1909 } else { |
1911 ASSERT(r.IsTagged()); | 1910 ASSERT(r.IsTagged()); |
1912 Register reg = ToRegister(instr->value()); | 1911 Register reg = ToRegister(instr->value()); |
1913 HType type = instr->hydrogen()->value()->type(); | 1912 HType type = instr->hydrogen()->value()->type(); |
1914 if (type.IsBoolean()) { | 1913 if (type.IsBoolean()) { |
1915 ASSERT(!info()->IsStub()); | 1914 ASSERT(!info()->IsStub()); |
1916 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 1915 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
1917 EmitBranch(true_block, false_block, equal); | 1916 EmitBranch(instr, equal); |
1918 } else if (type.IsSmi()) { | 1917 } else if (type.IsSmi()) { |
1919 ASSERT(!info()->IsStub()); | 1918 ASSERT(!info()->IsStub()); |
1920 __ SmiCompare(reg, Smi::FromInt(0)); | 1919 __ SmiCompare(reg, Smi::FromInt(0)); |
1921 EmitBranch(true_block, false_block, not_equal); | 1920 EmitBranch(instr, not_equal); |
1922 } else { | 1921 } else { |
1923 Label* true_label = chunk_->GetAssemblyLabel(true_block); | |
1924 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
1925 | |
1926 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); | 1922 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); |
1927 // Avoid deopts in the case where we've never executed this path before. | 1923 // Avoid deopts in the case where we've never executed this path before. |
1928 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); | 1924 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); |
1929 | 1925 |
1930 if (expected.Contains(ToBooleanStub::UNDEFINED)) { | 1926 if (expected.Contains(ToBooleanStub::UNDEFINED)) { |
1931 // undefined -> false. | 1927 // undefined -> false. |
1932 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); | 1928 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); |
1933 __ j(equal, false_label); | 1929 __ j(equal, instr->FalseLabel(chunk_)); |
1934 } | 1930 } |
1935 if (expected.Contains(ToBooleanStub::BOOLEAN)) { | 1931 if (expected.Contains(ToBooleanStub::BOOLEAN)) { |
1936 // true -> true. | 1932 // true -> true. |
1937 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 1933 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
1938 __ j(equal, true_label); | 1934 __ j(equal, instr->TrueLabel(chunk_)); |
1939 // false -> false. | 1935 // false -> false. |
1940 __ CompareRoot(reg, Heap::kFalseValueRootIndex); | 1936 __ CompareRoot(reg, Heap::kFalseValueRootIndex); |
1941 __ j(equal, false_label); | 1937 __ j(equal, instr->FalseLabel(chunk_)); |
1942 } | 1938 } |
1943 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { | 1939 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { |
1944 // 'null' -> false. | 1940 // 'null' -> false. |
1945 __ CompareRoot(reg, Heap::kNullValueRootIndex); | 1941 __ CompareRoot(reg, Heap::kNullValueRootIndex); |
1946 __ j(equal, false_label); | 1942 __ j(equal, instr->FalseLabel(chunk_)); |
1947 } | 1943 } |
1948 | 1944 |
1949 if (expected.Contains(ToBooleanStub::SMI)) { | 1945 if (expected.Contains(ToBooleanStub::SMI)) { |
1950 // Smis: 0 -> false, all other -> true. | 1946 // Smis: 0 -> false, all other -> true. |
1951 __ Cmp(reg, Smi::FromInt(0)); | 1947 __ Cmp(reg, Smi::FromInt(0)); |
1952 __ j(equal, false_label); | 1948 __ j(equal, instr->FalseLabel(chunk_)); |
1953 __ JumpIfSmi(reg, true_label); | 1949 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
1954 } else if (expected.NeedsMap()) { | 1950 } else if (expected.NeedsMap()) { |
1955 // If we need a map later and have a Smi -> deopt. | 1951 // If we need a map later and have a Smi -> deopt. |
1956 __ testb(reg, Immediate(kSmiTagMask)); | 1952 __ testb(reg, Immediate(kSmiTagMask)); |
1957 DeoptimizeIf(zero, instr->environment()); | 1953 DeoptimizeIf(zero, instr->environment()); |
1958 } | 1954 } |
1959 | 1955 |
1960 const Register map = kScratchRegister; | 1956 const Register map = kScratchRegister; |
1961 if (expected.NeedsMap()) { | 1957 if (expected.NeedsMap()) { |
1962 __ movq(map, FieldOperand(reg, HeapObject::kMapOffset)); | 1958 __ movq(map, FieldOperand(reg, HeapObject::kMapOffset)); |
1963 | 1959 |
1964 if (expected.CanBeUndetectable()) { | 1960 if (expected.CanBeUndetectable()) { |
1965 // Undetectable -> false. | 1961 // Undetectable -> false. |
1966 __ testb(FieldOperand(map, Map::kBitFieldOffset), | 1962 __ testb(FieldOperand(map, Map::kBitFieldOffset), |
1967 Immediate(1 << Map::kIsUndetectable)); | 1963 Immediate(1 << Map::kIsUndetectable)); |
1968 __ j(not_zero, false_label); | 1964 __ j(not_zero, instr->FalseLabel(chunk_)); |
1969 } | 1965 } |
1970 } | 1966 } |
1971 | 1967 |
1972 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { | 1968 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { |
1973 // spec object -> true. | 1969 // spec object -> true. |
1974 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); | 1970 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); |
1975 __ j(above_equal, true_label); | 1971 __ j(above_equal, instr->TrueLabel(chunk_)); |
1976 } | 1972 } |
1977 | 1973 |
1978 if (expected.Contains(ToBooleanStub::STRING)) { | 1974 if (expected.Contains(ToBooleanStub::STRING)) { |
1979 // String value -> false iff empty. | 1975 // String value -> false iff empty. |
1980 Label not_string; | 1976 Label not_string; |
1981 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); | 1977 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); |
1982 __ j(above_equal, ¬_string, Label::kNear); | 1978 __ j(above_equal, ¬_string, Label::kNear); |
1983 __ cmpq(FieldOperand(reg, String::kLengthOffset), Immediate(0)); | 1979 __ cmpq(FieldOperand(reg, String::kLengthOffset), Immediate(0)); |
1984 __ j(not_zero, true_label); | 1980 __ j(not_zero, instr->TrueLabel(chunk_)); |
1985 __ jmp(false_label); | 1981 __ jmp(instr->FalseLabel(chunk_)); |
1986 __ bind(¬_string); | 1982 __ bind(¬_string); |
1987 } | 1983 } |
1988 | 1984 |
1989 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { | 1985 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { |
1990 // heap number -> false iff +0, -0, or NaN. | 1986 // heap number -> false iff +0, -0, or NaN. |
1991 Label not_heap_number; | 1987 Label not_heap_number; |
1992 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); | 1988 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); |
1993 __ j(not_equal, ¬_heap_number, Label::kNear); | 1989 __ j(not_equal, ¬_heap_number, Label::kNear); |
1994 __ xorps(xmm0, xmm0); | 1990 __ xorps(xmm0, xmm0); |
1995 __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset)); | 1991 __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset)); |
1996 __ j(zero, false_label); | 1992 __ j(zero, instr->FalseLabel(chunk_)); |
1997 __ jmp(true_label); | 1993 __ jmp(instr->TrueLabel(chunk_)); |
1998 __ bind(¬_heap_number); | 1994 __ bind(¬_heap_number); |
1999 } | 1995 } |
2000 | 1996 |
2001 // We've seen something for the first time -> deopt. | 1997 // We've seen something for the first time -> deopt. |
2002 DeoptimizeIf(no_condition, instr->environment()); | 1998 DeoptimizeIf(no_condition, instr->environment()); |
2003 } | 1999 } |
2004 } | 2000 } |
2005 } | 2001 } |
2006 | 2002 |
2007 | 2003 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2041 default: | 2037 default: |
2042 UNREACHABLE(); | 2038 UNREACHABLE(); |
2043 } | 2039 } |
2044 return cond; | 2040 return cond; |
2045 } | 2041 } |
2046 | 2042 |
2047 | 2043 |
2048 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 2044 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
2049 LOperand* left = instr->left(); | 2045 LOperand* left = instr->left(); |
2050 LOperand* right = instr->right(); | 2046 LOperand* right = instr->right(); |
2051 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2052 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2053 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | 2047 Condition cc = TokenToCondition(instr->op(), instr->is_double()); |
2054 | 2048 |
2055 if (left->IsConstantOperand() && right->IsConstantOperand()) { | 2049 if (left->IsConstantOperand() && right->IsConstantOperand()) { |
2056 // We can statically evaluate the comparison. | 2050 // We can statically evaluate the comparison. |
2057 double left_val = ToDouble(LConstantOperand::cast(left)); | 2051 double left_val = ToDouble(LConstantOperand::cast(left)); |
2058 double right_val = ToDouble(LConstantOperand::cast(right)); | 2052 double right_val = ToDouble(LConstantOperand::cast(right)); |
2059 int next_block = | 2053 int next_block = EvalComparison(instr->op(), left_val, right_val) ? |
2060 EvalComparison(instr->op(), left_val, right_val) ? true_block | 2054 instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_); |
2061 : false_block; | |
2062 EmitGoto(next_block); | 2055 EmitGoto(next_block); |
2063 } else { | 2056 } else { |
2064 if (instr->is_double()) { | 2057 if (instr->is_double()) { |
2065 // Don't base result on EFLAGS when a NaN is involved. Instead | 2058 // Don't base result on EFLAGS when a NaN is involved. Instead |
2066 // jump to the false block. | 2059 // jump to the false block. |
2067 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); | 2060 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); |
2068 __ j(parity_even, chunk_->GetAssemblyLabel(false_block)); | 2061 __ j(parity_even, instr->FalseLabel(chunk_)); |
2069 } else { | 2062 } else { |
2070 int32_t value; | 2063 int32_t value; |
2071 if (right->IsConstantOperand()) { | 2064 if (right->IsConstantOperand()) { |
2072 value = ToInteger32(LConstantOperand::cast(right)); | 2065 value = ToInteger32(LConstantOperand::cast(right)); |
2073 if (instr->hydrogen_value()->representation().IsSmi()) { | 2066 if (instr->hydrogen_value()->representation().IsSmi()) { |
2074 __ Cmp(ToRegister(left), Smi::FromInt(value)); | 2067 __ Cmp(ToRegister(left), Smi::FromInt(value)); |
2075 } else { | 2068 } else { |
2076 __ cmpl(ToRegister(left), Immediate(value)); | 2069 __ cmpl(ToRegister(left), Immediate(value)); |
2077 } | 2070 } |
2078 } else if (left->IsConstantOperand()) { | 2071 } else if (left->IsConstantOperand()) { |
(...skipping 18 matching lines...) Expand all Loading... |
2097 __ cmpq(ToRegister(left), ToOperand(right)); | 2090 __ cmpq(ToRegister(left), ToOperand(right)); |
2098 } | 2091 } |
2099 } else { | 2092 } else { |
2100 if (right->IsRegister()) { | 2093 if (right->IsRegister()) { |
2101 __ cmpl(ToRegister(left), ToRegister(right)); | 2094 __ cmpl(ToRegister(left), ToRegister(right)); |
2102 } else { | 2095 } else { |
2103 __ cmpl(ToRegister(left), ToOperand(right)); | 2096 __ cmpl(ToRegister(left), ToOperand(right)); |
2104 } | 2097 } |
2105 } | 2098 } |
2106 } | 2099 } |
2107 EmitBranch(true_block, false_block, cc); | 2100 EmitBranch(instr, cc); |
2108 } | 2101 } |
2109 } | 2102 } |
2110 | 2103 |
2111 | 2104 |
2112 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { | 2105 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { |
2113 Register left = ToRegister(instr->left()); | 2106 Register left = ToRegister(instr->left()); |
2114 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2115 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2116 | 2107 |
2117 if (instr->right()->IsConstantOperand()) { | 2108 if (instr->right()->IsConstantOperand()) { |
2118 Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right())); | 2109 Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right())); |
2119 __ CmpObject(left, right); | 2110 __ CmpObject(left, right); |
2120 } else { | 2111 } else { |
2121 Register right = ToRegister(instr->right()); | 2112 Register right = ToRegister(instr->right()); |
2122 __ cmpq(left, right); | 2113 __ cmpq(left, right); |
2123 } | 2114 } |
2124 EmitBranch(true_block, false_block, equal); | 2115 EmitBranch(instr, equal); |
2125 } | 2116 } |
2126 | 2117 |
2127 | 2118 |
2128 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { | 2119 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { |
2129 Register left = ToRegister(instr->left()); | 2120 Register left = ToRegister(instr->left()); |
2130 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2131 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2132 | 2121 |
2133 __ cmpq(left, Immediate(instr->hydrogen()->right())); | 2122 __ cmpq(left, Immediate(instr->hydrogen()->right())); |
2134 EmitBranch(true_block, false_block, equal); | 2123 EmitBranch(instr, equal); |
2135 } | 2124 } |
2136 | 2125 |
2137 | 2126 |
2138 Condition LCodeGen::EmitIsObject(Register input, | 2127 Condition LCodeGen::EmitIsObject(Register input, |
2139 Label* is_not_object, | 2128 Label* is_not_object, |
2140 Label* is_object) { | 2129 Label* is_object) { |
2141 ASSERT(!input.is(kScratchRegister)); | 2130 ASSERT(!input.is(kScratchRegister)); |
2142 | 2131 |
2143 __ JumpIfSmi(input, is_not_object); | 2132 __ JumpIfSmi(input, is_not_object); |
2144 | 2133 |
(...skipping 11 matching lines...) Expand all Loading... |
2156 __ cmpb(kScratchRegister, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 2145 __ cmpb(kScratchRegister, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
2157 __ j(below, is_not_object); | 2146 __ j(below, is_not_object); |
2158 __ cmpb(kScratchRegister, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 2147 __ cmpb(kScratchRegister, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
2159 return below_equal; | 2148 return below_equal; |
2160 } | 2149 } |
2161 | 2150 |
2162 | 2151 |
2163 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 2152 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
2164 Register reg = ToRegister(instr->value()); | 2153 Register reg = ToRegister(instr->value()); |
2165 | 2154 |
2166 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2155 Condition true_cond = EmitIsObject( |
2167 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2156 reg, instr->FalseLabel(chunk_), instr->TrueLabel(chunk_)); |
2168 Label* true_label = chunk_->GetAssemblyLabel(true_block); | |
2169 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
2170 | 2157 |
2171 Condition true_cond = EmitIsObject(reg, false_label, true_label); | 2158 EmitBranch(instr, true_cond); |
2172 | |
2173 EmitBranch(true_block, false_block, true_cond); | |
2174 } | 2159 } |
2175 | 2160 |
2176 | 2161 |
2177 Condition LCodeGen::EmitIsString(Register input, | 2162 Condition LCodeGen::EmitIsString(Register input, |
2178 Register temp1, | 2163 Register temp1, |
2179 Label* is_not_string) { | 2164 Label* is_not_string) { |
2180 __ JumpIfSmi(input, is_not_string); | 2165 __ JumpIfSmi(input, is_not_string); |
2181 Condition cond = masm_->IsObjectStringType(input, temp1, temp1); | 2166 Condition cond = masm_->IsObjectStringType(input, temp1, temp1); |
2182 | 2167 |
2183 return cond; | 2168 return cond; |
2184 } | 2169 } |
2185 | 2170 |
2186 | 2171 |
2187 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { | 2172 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { |
2188 Register reg = ToRegister(instr->value()); | 2173 Register reg = ToRegister(instr->value()); |
2189 Register temp = ToRegister(instr->temp()); | 2174 Register temp = ToRegister(instr->temp()); |
2190 | 2175 |
2191 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2176 Condition true_cond = EmitIsString(reg, temp, instr->FalseLabel(chunk_)); |
2192 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2193 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
2194 | 2177 |
2195 Condition true_cond = EmitIsString(reg, temp, false_label); | 2178 EmitBranch(instr, true_cond); |
2196 | |
2197 EmitBranch(true_block, false_block, true_cond); | |
2198 } | 2179 } |
2199 | 2180 |
2200 | 2181 |
2201 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 2182 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
2202 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2203 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2204 | |
2205 Condition is_smi; | 2183 Condition is_smi; |
2206 if (instr->value()->IsRegister()) { | 2184 if (instr->value()->IsRegister()) { |
2207 Register input = ToRegister(instr->value()); | 2185 Register input = ToRegister(instr->value()); |
2208 is_smi = masm()->CheckSmi(input); | 2186 is_smi = masm()->CheckSmi(input); |
2209 } else { | 2187 } else { |
2210 Operand input = ToOperand(instr->value()); | 2188 Operand input = ToOperand(instr->value()); |
2211 is_smi = masm()->CheckSmi(input); | 2189 is_smi = masm()->CheckSmi(input); |
2212 } | 2190 } |
2213 EmitBranch(true_block, false_block, is_smi); | 2191 EmitBranch(instr, is_smi); |
2214 } | 2192 } |
2215 | 2193 |
2216 | 2194 |
2217 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { | 2195 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { |
2218 Register input = ToRegister(instr->value()); | 2196 Register input = ToRegister(instr->value()); |
2219 Register temp = ToRegister(instr->temp()); | 2197 Register temp = ToRegister(instr->temp()); |
2220 | 2198 |
2221 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2199 __ JumpIfSmi(input, instr->FalseLabel(chunk_)); |
2222 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2223 | |
2224 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); | |
2225 __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); | 2200 __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); |
2226 __ testb(FieldOperand(temp, Map::kBitFieldOffset), | 2201 __ testb(FieldOperand(temp, Map::kBitFieldOffset), |
2227 Immediate(1 << Map::kIsUndetectable)); | 2202 Immediate(1 << Map::kIsUndetectable)); |
2228 EmitBranch(true_block, false_block, not_zero); | 2203 EmitBranch(instr, not_zero); |
2229 } | 2204 } |
2230 | 2205 |
2231 | 2206 |
2232 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { | 2207 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { |
2233 Token::Value op = instr->op(); | 2208 Token::Value op = instr->op(); |
2234 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2235 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2236 | 2209 |
2237 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 2210 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
2238 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2211 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2239 | 2212 |
2240 Condition condition = TokenToCondition(op, false); | 2213 Condition condition = TokenToCondition(op, false); |
2241 __ testq(rax, rax); | 2214 __ testq(rax, rax); |
2242 | 2215 |
2243 EmitBranch(true_block, false_block, condition); | 2216 EmitBranch(instr, condition); |
2244 } | 2217 } |
2245 | 2218 |
2246 | 2219 |
2247 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { | 2220 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { |
2248 InstanceType from = instr->from(); | 2221 InstanceType from = instr->from(); |
2249 InstanceType to = instr->to(); | 2222 InstanceType to = instr->to(); |
2250 if (from == FIRST_TYPE) return to; | 2223 if (from == FIRST_TYPE) return to; |
2251 ASSERT(from == to || to == LAST_TYPE); | 2224 ASSERT(from == to || to == LAST_TYPE); |
2252 return from; | 2225 return from; |
2253 } | 2226 } |
2254 | 2227 |
2255 | 2228 |
2256 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { | 2229 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { |
2257 InstanceType from = instr->from(); | 2230 InstanceType from = instr->from(); |
2258 InstanceType to = instr->to(); | 2231 InstanceType to = instr->to(); |
2259 if (from == to) return equal; | 2232 if (from == to) return equal; |
2260 if (to == LAST_TYPE) return above_equal; | 2233 if (to == LAST_TYPE) return above_equal; |
2261 if (from == FIRST_TYPE) return below_equal; | 2234 if (from == FIRST_TYPE) return below_equal; |
2262 UNREACHABLE(); | 2235 UNREACHABLE(); |
2263 return equal; | 2236 return equal; |
2264 } | 2237 } |
2265 | 2238 |
2266 | 2239 |
2267 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 2240 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
2268 Register input = ToRegister(instr->value()); | 2241 Register input = ToRegister(instr->value()); |
2269 | 2242 |
2270 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2243 __ JumpIfSmi(input, instr->FalseLabel(chunk_)); |
2271 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2272 | |
2273 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
2274 | |
2275 __ JumpIfSmi(input, false_label); | |
2276 | 2244 |
2277 __ CmpObjectType(input, TestType(instr->hydrogen()), kScratchRegister); | 2245 __ CmpObjectType(input, TestType(instr->hydrogen()), kScratchRegister); |
2278 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); | 2246 EmitBranch(instr, BranchCondition(instr->hydrogen())); |
2279 } | 2247 } |
2280 | 2248 |
2281 | 2249 |
2282 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { | 2250 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { |
2283 Register input = ToRegister(instr->value()); | 2251 Register input = ToRegister(instr->value()); |
2284 Register result = ToRegister(instr->result()); | 2252 Register result = ToRegister(instr->result()); |
2285 | 2253 |
2286 __ AssertString(input); | 2254 __ AssertString(input); |
2287 | 2255 |
2288 __ movl(result, FieldOperand(input, String::kHashFieldOffset)); | 2256 __ movl(result, FieldOperand(input, String::kHashFieldOffset)); |
2289 ASSERT(String::kHashShift >= kSmiTagSize); | 2257 ASSERT(String::kHashShift >= kSmiTagSize); |
2290 __ IndexFromHash(result, result); | 2258 __ IndexFromHash(result, result); |
2291 } | 2259 } |
2292 | 2260 |
2293 | 2261 |
2294 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 2262 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
2295 LHasCachedArrayIndexAndBranch* instr) { | 2263 LHasCachedArrayIndexAndBranch* instr) { |
2296 Register input = ToRegister(instr->value()); | 2264 Register input = ToRegister(instr->value()); |
2297 | 2265 |
2298 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2299 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2300 | |
2301 __ testl(FieldOperand(input, String::kHashFieldOffset), | 2266 __ testl(FieldOperand(input, String::kHashFieldOffset), |
2302 Immediate(String::kContainsCachedArrayIndexMask)); | 2267 Immediate(String::kContainsCachedArrayIndexMask)); |
2303 EmitBranch(true_block, false_block, equal); | 2268 EmitBranch(instr, equal); |
2304 } | 2269 } |
2305 | 2270 |
2306 | 2271 |
2307 // Branches to a label or falls through with the answer in the z flag. | 2272 // Branches to a label or falls through with the answer in the z flag. |
2308 // Trashes the temp register. | 2273 // Trashes the temp register. |
2309 void LCodeGen::EmitClassOfTest(Label* is_true, | 2274 void LCodeGen::EmitClassOfTest(Label* is_true, |
2310 Label* is_false, | 2275 Label* is_false, |
2311 Handle<String> class_name, | 2276 Handle<String> class_name, |
2312 Register input, | 2277 Register input, |
2313 Register temp, | 2278 Register temp, |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2371 // End with the answer in the z flag. | 2336 // End with the answer in the z flag. |
2372 } | 2337 } |
2373 | 2338 |
2374 | 2339 |
2375 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 2340 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
2376 Register input = ToRegister(instr->value()); | 2341 Register input = ToRegister(instr->value()); |
2377 Register temp = ToRegister(instr->temp()); | 2342 Register temp = ToRegister(instr->temp()); |
2378 Register temp2 = ToRegister(instr->temp2()); | 2343 Register temp2 = ToRegister(instr->temp2()); |
2379 Handle<String> class_name = instr->hydrogen()->class_name(); | 2344 Handle<String> class_name = instr->hydrogen()->class_name(); |
2380 | 2345 |
2381 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2346 EmitClassOfTest(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), |
2382 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2347 class_name, input, temp, temp2); |
2383 | 2348 |
2384 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 2349 EmitBranch(instr, equal); |
2385 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
2386 | |
2387 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); | |
2388 | |
2389 EmitBranch(true_block, false_block, equal); | |
2390 } | 2350 } |
2391 | 2351 |
2392 | 2352 |
2393 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 2353 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
2394 Register reg = ToRegister(instr->value()); | 2354 Register reg = ToRegister(instr->value()); |
2395 int true_block = instr->true_block_id(); | |
2396 int false_block = instr->false_block_id(); | |
2397 | 2355 |
2398 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); | 2356 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); |
2399 EmitBranch(true_block, false_block, equal); | 2357 EmitBranch(instr, equal); |
2400 } | 2358 } |
2401 | 2359 |
2402 | 2360 |
2403 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 2361 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
2404 InstanceofStub stub(InstanceofStub::kNoFlags); | 2362 InstanceofStub stub(InstanceofStub::kNoFlags); |
2405 __ push(ToRegister(instr->left())); | 2363 __ push(ToRegister(instr->left())); |
2406 __ push(ToRegister(instr->right())); | 2364 __ push(ToRegister(instr->right())); |
2407 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 2365 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
2408 Label true_value, done; | 2366 Label true_value, done; |
2409 __ testq(rax, rax); | 2367 __ testq(rax, rax); |
(...skipping 2841 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5251 } else if (operand->IsRegister()) { | 5209 } else if (operand->IsRegister()) { |
5252 __ push(ToRegister(operand)); | 5210 __ push(ToRegister(operand)); |
5253 } else { | 5211 } else { |
5254 __ push(ToOperand(operand)); | 5212 __ push(ToOperand(operand)); |
5255 } | 5213 } |
5256 } | 5214 } |
5257 | 5215 |
5258 | 5216 |
5259 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 5217 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
5260 Register input = ToRegister(instr->value()); | 5218 Register input = ToRegister(instr->value()); |
5261 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
5262 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
5263 Label* true_label = chunk_->GetAssemblyLabel(true_block); | |
5264 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
5265 | 5219 |
5266 Condition final_branch_condition = | 5220 Condition final_branch_condition = |
5267 EmitTypeofIs(true_label, false_label, input, instr->type_literal()); | 5221 EmitTypeofIs(instr->TrueLabel(chunk_), |
| 5222 instr->FalseLabel(chunk_), input, instr->type_literal()); |
5268 if (final_branch_condition != no_condition) { | 5223 if (final_branch_condition != no_condition) { |
5269 EmitBranch(true_block, false_block, final_branch_condition); | 5224 EmitBranch(instr, final_branch_condition); |
5270 } | 5225 } |
5271 } | 5226 } |
5272 | 5227 |
5273 | 5228 |
5274 Condition LCodeGen::EmitTypeofIs(Label* true_label, | 5229 Condition LCodeGen::EmitTypeofIs(Label* true_label, |
5275 Label* false_label, | 5230 Label* false_label, |
5276 Register input, | 5231 Register input, |
5277 Handle<String> type_name) { | 5232 Handle<String> type_name) { |
5278 Condition final_branch_condition = no_condition; | 5233 Condition final_branch_condition = no_condition; |
5279 if (type_name->Equals(heap()->number_string())) { | 5234 if (type_name->Equals(heap()->number_string())) { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5342 } else { | 5297 } else { |
5343 __ jmp(false_label); | 5298 __ jmp(false_label); |
5344 } | 5299 } |
5345 | 5300 |
5346 return final_branch_condition; | 5301 return final_branch_condition; |
5347 } | 5302 } |
5348 | 5303 |
5349 | 5304 |
5350 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 5305 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
5351 Register temp = ToRegister(instr->temp()); | 5306 Register temp = ToRegister(instr->temp()); |
5352 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
5353 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
5354 | 5307 |
5355 EmitIsConstructCall(temp); | 5308 EmitIsConstructCall(temp); |
5356 EmitBranch(true_block, false_block, equal); | 5309 EmitBranch(instr, equal); |
5357 } | 5310 } |
5358 | 5311 |
5359 | 5312 |
5360 void LCodeGen::EmitIsConstructCall(Register temp) { | 5313 void LCodeGen::EmitIsConstructCall(Register temp) { |
5361 // Get the frame pointer for the calling frame. | 5314 // Get the frame pointer for the calling frame. |
5362 __ movq(temp, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 5315 __ movq(temp, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
5363 | 5316 |
5364 // Skip the arguments adaptor frame if it exists. | 5317 // Skip the arguments adaptor frame if it exists. |
5365 Label check_frame_marker; | 5318 Label check_frame_marker; |
5366 __ Cmp(Operand(temp, StandardFrameConstants::kContextOffset), | 5319 __ Cmp(Operand(temp, StandardFrameConstants::kContextOffset), |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5604 FixedArray::kHeaderSize - kPointerSize)); | 5557 FixedArray::kHeaderSize - kPointerSize)); |
5605 __ bind(&done); | 5558 __ bind(&done); |
5606 } | 5559 } |
5607 | 5560 |
5608 | 5561 |
5609 #undef __ | 5562 #undef __ |
5610 | 5563 |
5611 } } // namespace v8::internal | 5564 } } // namespace v8::internal |
5612 | 5565 |
5613 #endif // V8_TARGET_ARCH_X64 | 5566 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |