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