| 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 |