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