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