OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
6 | 6 |
7 #include "src/crankshaft/ia32/lithium-codegen-ia32.h" | 7 #include "src/crankshaft/ia32/lithium-codegen-ia32.h" |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
(...skipping 1836 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1847 DCHECK(!info()->IsStub()); | 1847 DCHECK(!info()->IsStub()); |
1848 XMMRegister xmm_scratch = double_scratch0(); | 1848 XMMRegister xmm_scratch = double_scratch0(); |
1849 __ xorps(xmm_scratch, xmm_scratch); | 1849 __ xorps(xmm_scratch, xmm_scratch); |
1850 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); | 1850 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); |
1851 EmitBranch(instr, not_equal); | 1851 EmitBranch(instr, not_equal); |
1852 } else if (type.IsString()) { | 1852 } else if (type.IsString()) { |
1853 DCHECK(!info()->IsStub()); | 1853 DCHECK(!info()->IsStub()); |
1854 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); | 1854 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); |
1855 EmitBranch(instr, not_equal); | 1855 EmitBranch(instr, not_equal); |
1856 } else { | 1856 } else { |
1857 ToBooleanICStub::Types expected = | 1857 ToBooleanHints expected = instr->hydrogen()->expected_input_types(); |
1858 instr->hydrogen()->expected_input_types(); | 1858 if (expected == ToBooleanHint::kNone) expected = ToBooleanHint::kAny; |
1859 if (expected.IsEmpty()) expected = ToBooleanICStub::Types::Generic(); | |
1860 | 1859 |
1861 if (expected.Contains(ToBooleanICStub::UNDEFINED)) { | 1860 if (expected & ToBooleanHint::kUndefined) { |
1862 // undefined -> false. | 1861 // undefined -> false. |
1863 __ cmp(reg, factory()->undefined_value()); | 1862 __ cmp(reg, factory()->undefined_value()); |
1864 __ j(equal, instr->FalseLabel(chunk_)); | 1863 __ j(equal, instr->FalseLabel(chunk_)); |
1865 } | 1864 } |
1866 if (expected.Contains(ToBooleanICStub::BOOLEAN)) { | 1865 if (expected & ToBooleanHint::kBoolean) { |
1867 // true -> true. | 1866 // true -> true. |
1868 __ cmp(reg, factory()->true_value()); | 1867 __ cmp(reg, factory()->true_value()); |
1869 __ j(equal, instr->TrueLabel(chunk_)); | 1868 __ j(equal, instr->TrueLabel(chunk_)); |
1870 // false -> false. | 1869 // false -> false. |
1871 __ cmp(reg, factory()->false_value()); | 1870 __ cmp(reg, factory()->false_value()); |
1872 __ j(equal, instr->FalseLabel(chunk_)); | 1871 __ j(equal, instr->FalseLabel(chunk_)); |
1873 } | 1872 } |
1874 if (expected.Contains(ToBooleanICStub::NULL_TYPE)) { | 1873 if (expected & ToBooleanHint::kNull) { |
1875 // 'null' -> false. | 1874 // 'null' -> false. |
1876 __ cmp(reg, factory()->null_value()); | 1875 __ cmp(reg, factory()->null_value()); |
1877 __ j(equal, instr->FalseLabel(chunk_)); | 1876 __ j(equal, instr->FalseLabel(chunk_)); |
1878 } | 1877 } |
1879 | 1878 |
1880 if (expected.Contains(ToBooleanICStub::SMI)) { | 1879 if (expected & ToBooleanHint::kSmallInteger) { |
1881 // Smis: 0 -> false, all other -> true. | 1880 // Smis: 0 -> false, all other -> true. |
1882 __ test(reg, Operand(reg)); | 1881 __ test(reg, Operand(reg)); |
1883 __ j(equal, instr->FalseLabel(chunk_)); | 1882 __ j(equal, instr->FalseLabel(chunk_)); |
1884 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); | 1883 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
1885 } else if (expected.NeedsMap()) { | 1884 } else if (expected & ToBooleanHint::kNeedsMap) { |
1886 // If we need a map later and have a Smi -> deopt. | 1885 // If we need a map later and have a Smi -> deopt. |
1887 __ test(reg, Immediate(kSmiTagMask)); | 1886 __ test(reg, Immediate(kSmiTagMask)); |
1888 DeoptimizeIf(zero, instr, DeoptimizeReason::kSmi); | 1887 DeoptimizeIf(zero, instr, DeoptimizeReason::kSmi); |
1889 } | 1888 } |
1890 | 1889 |
1891 Register map = no_reg; // Keep the compiler happy. | 1890 Register map = no_reg; // Keep the compiler happy. |
1892 if (expected.NeedsMap()) { | 1891 if (expected & ToBooleanHint::kNeedsMap) { |
1893 map = ToRegister(instr->temp()); | 1892 map = ToRegister(instr->temp()); |
1894 DCHECK(!map.is(reg)); | 1893 DCHECK(!map.is(reg)); |
1895 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); | 1894 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); |
1896 | 1895 |
1897 if (expected.CanBeUndetectable()) { | 1896 if (expected & ToBooleanHint::kCanBeUndetectable) { |
1898 // Undetectable -> false. | 1897 // Undetectable -> false. |
1899 __ test_b(FieldOperand(map, Map::kBitFieldOffset), | 1898 __ test_b(FieldOperand(map, Map::kBitFieldOffset), |
1900 Immediate(1 << Map::kIsUndetectable)); | 1899 Immediate(1 << Map::kIsUndetectable)); |
1901 __ j(not_zero, instr->FalseLabel(chunk_)); | 1900 __ j(not_zero, instr->FalseLabel(chunk_)); |
1902 } | 1901 } |
1903 } | 1902 } |
1904 | 1903 |
1905 if (expected.Contains(ToBooleanICStub::SPEC_OBJECT)) { | 1904 if (expected & ToBooleanHint::kReceiver) { |
1906 // spec object -> true. | 1905 // spec object -> true. |
1907 __ CmpInstanceType(map, FIRST_JS_RECEIVER_TYPE); | 1906 __ CmpInstanceType(map, FIRST_JS_RECEIVER_TYPE); |
1908 __ j(above_equal, instr->TrueLabel(chunk_)); | 1907 __ j(above_equal, instr->TrueLabel(chunk_)); |
1909 } | 1908 } |
1910 | 1909 |
1911 if (expected.Contains(ToBooleanICStub::STRING)) { | 1910 if (expected & ToBooleanHint::kString) { |
1912 // String value -> false iff empty. | 1911 // String value -> false iff empty. |
1913 Label not_string; | 1912 Label not_string; |
1914 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); | 1913 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); |
1915 __ j(above_equal, ¬_string, Label::kNear); | 1914 __ j(above_equal, ¬_string, Label::kNear); |
1916 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); | 1915 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); |
1917 __ j(not_zero, instr->TrueLabel(chunk_)); | 1916 __ j(not_zero, instr->TrueLabel(chunk_)); |
1918 __ jmp(instr->FalseLabel(chunk_)); | 1917 __ jmp(instr->FalseLabel(chunk_)); |
1919 __ bind(¬_string); | 1918 __ bind(¬_string); |
1920 } | 1919 } |
1921 | 1920 |
1922 if (expected.Contains(ToBooleanICStub::SYMBOL)) { | 1921 if (expected & ToBooleanHint::kSymbol) { |
1923 // Symbol value -> true. | 1922 // Symbol value -> true. |
1924 __ CmpInstanceType(map, SYMBOL_TYPE); | 1923 __ CmpInstanceType(map, SYMBOL_TYPE); |
1925 __ j(equal, instr->TrueLabel(chunk_)); | 1924 __ j(equal, instr->TrueLabel(chunk_)); |
1926 } | 1925 } |
1927 | 1926 |
1928 if (expected.Contains(ToBooleanICStub::SIMD_VALUE)) { | 1927 if (expected & ToBooleanHint::kSimdValue) { |
1929 // SIMD value -> true. | 1928 // SIMD value -> true. |
1930 __ CmpInstanceType(map, SIMD128_VALUE_TYPE); | 1929 __ CmpInstanceType(map, SIMD128_VALUE_TYPE); |
1931 __ j(equal, instr->TrueLabel(chunk_)); | 1930 __ j(equal, instr->TrueLabel(chunk_)); |
1932 } | 1931 } |
1933 | 1932 |
1934 if (expected.Contains(ToBooleanICStub::HEAP_NUMBER)) { | 1933 if (expected & ToBooleanHint::kHeapNumber) { |
1935 // heap number -> false iff +0, -0, or NaN. | 1934 // heap number -> false iff +0, -0, or NaN. |
1936 Label not_heap_number; | 1935 Label not_heap_number; |
1937 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 1936 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
1938 factory()->heap_number_map()); | 1937 factory()->heap_number_map()); |
1939 __ j(not_equal, ¬_heap_number, Label::kNear); | 1938 __ j(not_equal, ¬_heap_number, Label::kNear); |
1940 XMMRegister xmm_scratch = double_scratch0(); | 1939 XMMRegister xmm_scratch = double_scratch0(); |
1941 __ xorps(xmm_scratch, xmm_scratch); | 1940 __ xorps(xmm_scratch, xmm_scratch); |
1942 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); | 1941 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); |
1943 __ j(zero, instr->FalseLabel(chunk_)); | 1942 __ j(zero, instr->FalseLabel(chunk_)); |
1944 __ jmp(instr->TrueLabel(chunk_)); | 1943 __ jmp(instr->TrueLabel(chunk_)); |
1945 __ bind(¬_heap_number); | 1944 __ bind(¬_heap_number); |
1946 } | 1945 } |
1947 | 1946 |
1948 if (!expected.IsGeneric()) { | 1947 if (expected != ToBooleanHint::kAny) { |
1949 // We've seen something for the first time -> deopt. | 1948 // We've seen something for the first time -> deopt. |
1950 // This can only happen if we are not generic already. | 1949 // This can only happen if we are not generic already. |
1951 DeoptimizeIf(no_condition, instr, DeoptimizeReason::kUnexpectedObject); | 1950 DeoptimizeIf(no_condition, instr, DeoptimizeReason::kUnexpectedObject); |
1952 } | 1951 } |
1953 } | 1952 } |
1954 } | 1953 } |
1955 } | 1954 } |
1956 | 1955 |
1957 | 1956 |
1958 void LCodeGen::EmitGoto(int block) { | 1957 void LCodeGen::EmitGoto(int block) { |
(...skipping 3191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5150 __ bind(deferred->exit()); | 5149 __ bind(deferred->exit()); |
5151 __ bind(&done); | 5150 __ bind(&done); |
5152 } | 5151 } |
5153 | 5152 |
5154 #undef __ | 5153 #undef __ |
5155 | 5154 |
5156 } // namespace internal | 5155 } // namespace internal |
5157 } // namespace v8 | 5156 } // namespace v8 |
5158 | 5157 |
5159 #endif // V8_TARGET_ARCH_IA32 | 5158 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |