OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 1952 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1963 } | 1963 } |
1964 | 1964 |
1965 | 1965 |
1966 int LCodeGen::GetNextEmittedBlock() const { | 1966 int LCodeGen::GetNextEmittedBlock() const { |
1967 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { | 1967 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { |
1968 if (!chunk_->GetLabel(i)->HasReplacement()) return i; | 1968 if (!chunk_->GetLabel(i)->HasReplacement()) return i; |
1969 } | 1969 } |
1970 return -1; | 1970 return -1; |
1971 } | 1971 } |
1972 | 1972 |
| 1973 template<class InstrType> |
| 1974 void LCodeGen::EmitBranch(InstrType instr, |
| 1975 Condition cc, Register src1, const Operand& src2) { |
| 1976 int right_block = instr->FalseDestination(chunk_); |
| 1977 int left_block = instr->TrueDestination(chunk_); |
1973 | 1978 |
1974 void LCodeGen::EmitBranch(int left_block, int right_block, | |
1975 Condition cc, Register src1, const Operand& src2) { | |
1976 int next_block = GetNextEmittedBlock(); | 1979 int next_block = GetNextEmittedBlock(); |
1977 right_block = chunk_->LookupDestination(right_block); | |
1978 left_block = chunk_->LookupDestination(left_block); | |
1979 if (right_block == left_block) { | 1980 if (right_block == left_block) { |
1980 EmitGoto(left_block); | 1981 EmitGoto(left_block); |
1981 } else if (left_block == next_block) { | 1982 } else if (left_block == next_block) { |
1982 __ Branch(chunk_->GetAssemblyLabel(right_block), | 1983 __ Branch(chunk_->GetAssemblyLabel(right_block), |
1983 NegateCondition(cc), src1, src2); | 1984 NegateCondition(cc), src1, src2); |
1984 } else if (right_block == next_block) { | 1985 } else if (right_block == next_block) { |
1985 __ Branch(chunk_->GetAssemblyLabel(left_block), cc, src1, src2); | 1986 __ Branch(chunk_->GetAssemblyLabel(left_block), cc, src1, src2); |
1986 } else { | 1987 } else { |
1987 __ Branch(chunk_->GetAssemblyLabel(left_block), cc, src1, src2); | 1988 __ Branch(chunk_->GetAssemblyLabel(left_block), cc, src1, src2); |
1988 __ Branch(chunk_->GetAssemblyLabel(right_block)); | 1989 __ Branch(chunk_->GetAssemblyLabel(right_block)); |
1989 } | 1990 } |
1990 } | 1991 } |
1991 | 1992 |
1992 | 1993 |
1993 void LCodeGen::EmitBranchF(int left_block, int right_block, | 1994 template<class InstrType> |
| 1995 void LCodeGen::EmitBranchF(InstrType instr, |
1994 Condition cc, FPURegister src1, FPURegister src2) { | 1996 Condition cc, FPURegister src1, FPURegister src2) { |
| 1997 int right_block = instr->FalseDestination(chunk_); |
| 1998 int left_block = instr->TrueDestination(chunk_); |
| 1999 |
1995 int next_block = GetNextEmittedBlock(); | 2000 int next_block = GetNextEmittedBlock(); |
1996 right_block = chunk_->LookupDestination(right_block); | |
1997 left_block = chunk_->LookupDestination(left_block); | |
1998 if (right_block == left_block) { | 2001 if (right_block == left_block) { |
1999 EmitGoto(left_block); | 2002 EmitGoto(left_block); |
2000 } else if (left_block == next_block) { | 2003 } else if (left_block == next_block) { |
2001 __ BranchF(chunk_->GetAssemblyLabel(right_block), NULL, | 2004 __ BranchF(chunk_->GetAssemblyLabel(right_block), NULL, |
2002 NegateCondition(cc), src1, src2); | 2005 NegateCondition(cc), src1, src2); |
2003 } else if (right_block == next_block) { | 2006 } else if (right_block == next_block) { |
2004 __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL, cc, src1, src2); | 2007 __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL, cc, src1, src2); |
2005 } else { | 2008 } else { |
2006 __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL, cc, src1, src2); | 2009 __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL, cc, src1, src2); |
2007 __ Branch(chunk_->GetAssemblyLabel(right_block)); | 2010 __ Branch(chunk_->GetAssemblyLabel(right_block)); |
2008 } | 2011 } |
2009 } | 2012 } |
2010 | 2013 |
2011 | 2014 |
2012 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { | 2015 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { |
2013 __ stop("LDebugBreak"); | 2016 __ stop("LDebugBreak"); |
2014 } | 2017 } |
2015 | 2018 |
2016 | 2019 |
2017 void LCodeGen::DoBranch(LBranch* instr) { | 2020 void LCodeGen::DoBranch(LBranch* instr) { |
2018 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2019 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2020 | |
2021 Representation r = instr->hydrogen()->value()->representation(); | 2021 Representation r = instr->hydrogen()->value()->representation(); |
2022 if (r.IsInteger32() || r.IsSmi()) { | 2022 if (r.IsInteger32() || r.IsSmi()) { |
2023 ASSERT(!info()->IsStub()); | 2023 ASSERT(!info()->IsStub()); |
2024 Register reg = ToRegister(instr->value()); | 2024 Register reg = ToRegister(instr->value()); |
2025 EmitBranch(true_block, false_block, ne, reg, Operand(zero_reg)); | 2025 EmitBranch(instr, ne, reg, Operand(zero_reg)); |
2026 } else if (r.IsDouble()) { | 2026 } else if (r.IsDouble()) { |
2027 ASSERT(!info()->IsStub()); | 2027 ASSERT(!info()->IsStub()); |
2028 DoubleRegister reg = ToDoubleRegister(instr->value()); | 2028 DoubleRegister reg = ToDoubleRegister(instr->value()); |
2029 // Test the double value. Zero and NaN are false. | 2029 // Test the double value. Zero and NaN are false. |
2030 EmitBranchF(true_block, false_block, nue, reg, kDoubleRegZero); | 2030 EmitBranchF(instr, nue, reg, kDoubleRegZero); |
2031 } else { | 2031 } else { |
2032 ASSERT(r.IsTagged()); | 2032 ASSERT(r.IsTagged()); |
2033 Register reg = ToRegister(instr->value()); | 2033 Register reg = ToRegister(instr->value()); |
2034 HType type = instr->hydrogen()->value()->type(); | 2034 HType type = instr->hydrogen()->value()->type(); |
2035 if (type.IsBoolean()) { | 2035 if (type.IsBoolean()) { |
2036 ASSERT(!info()->IsStub()); | 2036 ASSERT(!info()->IsStub()); |
2037 __ LoadRoot(at, Heap::kTrueValueRootIndex); | 2037 __ LoadRoot(at, Heap::kTrueValueRootIndex); |
2038 EmitBranch(true_block, false_block, eq, reg, Operand(at)); | 2038 EmitBranch(instr, eq, reg, Operand(at)); |
2039 } else if (type.IsSmi()) { | 2039 } else if (type.IsSmi()) { |
2040 ASSERT(!info()->IsStub()); | 2040 ASSERT(!info()->IsStub()); |
2041 EmitBranch(true_block, false_block, ne, reg, Operand(zero_reg)); | 2041 EmitBranch(instr, ne, reg, Operand(zero_reg)); |
2042 } else { | 2042 } else { |
2043 Label* true_label = chunk_->GetAssemblyLabel(true_block); | |
2044 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
2045 | |
2046 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); | 2043 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); |
2047 // Avoid deopts in the case where we've never executed this path before. | 2044 // Avoid deopts in the case where we've never executed this path before. |
2048 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); | 2045 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); |
2049 | 2046 |
2050 if (expected.Contains(ToBooleanStub::UNDEFINED)) { | 2047 if (expected.Contains(ToBooleanStub::UNDEFINED)) { |
2051 // undefined -> false. | 2048 // undefined -> false. |
2052 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 2049 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
2053 __ Branch(false_label, eq, reg, Operand(at)); | 2050 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(at)); |
2054 } | 2051 } |
2055 if (expected.Contains(ToBooleanStub::BOOLEAN)) { | 2052 if (expected.Contains(ToBooleanStub::BOOLEAN)) { |
2056 // Boolean -> its value. | 2053 // Boolean -> its value. |
2057 __ LoadRoot(at, Heap::kTrueValueRootIndex); | 2054 __ LoadRoot(at, Heap::kTrueValueRootIndex); |
2058 __ Branch(true_label, eq, reg, Operand(at)); | 2055 __ Branch(instr->TrueLabel(chunk_), eq, reg, Operand(at)); |
2059 __ LoadRoot(at, Heap::kFalseValueRootIndex); | 2056 __ LoadRoot(at, Heap::kFalseValueRootIndex); |
2060 __ Branch(false_label, eq, reg, Operand(at)); | 2057 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(at)); |
2061 } | 2058 } |
2062 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { | 2059 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { |
2063 // 'null' -> false. | 2060 // 'null' -> false. |
2064 __ LoadRoot(at, Heap::kNullValueRootIndex); | 2061 __ LoadRoot(at, Heap::kNullValueRootIndex); |
2065 __ Branch(false_label, eq, reg, Operand(at)); | 2062 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(at)); |
2066 } | 2063 } |
2067 | 2064 |
2068 if (expected.Contains(ToBooleanStub::SMI)) { | 2065 if (expected.Contains(ToBooleanStub::SMI)) { |
2069 // Smis: 0 -> false, all other -> true. | 2066 // Smis: 0 -> false, all other -> true. |
2070 __ Branch(false_label, eq, reg, Operand(zero_reg)); | 2067 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(zero_reg)); |
2071 __ JumpIfSmi(reg, true_label); | 2068 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
2072 } else if (expected.NeedsMap()) { | 2069 } else if (expected.NeedsMap()) { |
2073 // If we need a map later and have a Smi -> deopt. | 2070 // If we need a map later and have a Smi -> deopt. |
2074 __ And(at, reg, Operand(kSmiTagMask)); | 2071 __ And(at, reg, Operand(kSmiTagMask)); |
2075 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); | 2072 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); |
2076 } | 2073 } |
2077 | 2074 |
2078 const Register map = scratch0(); | 2075 const Register map = scratch0(); |
2079 if (expected.NeedsMap()) { | 2076 if (expected.NeedsMap()) { |
2080 __ lw(map, FieldMemOperand(reg, HeapObject::kMapOffset)); | 2077 __ lw(map, FieldMemOperand(reg, HeapObject::kMapOffset)); |
2081 if (expected.CanBeUndetectable()) { | 2078 if (expected.CanBeUndetectable()) { |
2082 // Undetectable -> false. | 2079 // Undetectable -> false. |
2083 __ lbu(at, FieldMemOperand(map, Map::kBitFieldOffset)); | 2080 __ lbu(at, FieldMemOperand(map, Map::kBitFieldOffset)); |
2084 __ And(at, at, Operand(1 << Map::kIsUndetectable)); | 2081 __ And(at, at, Operand(1 << Map::kIsUndetectable)); |
2085 __ Branch(false_label, ne, at, Operand(zero_reg)); | 2082 __ Branch(instr->FalseLabel(chunk_), ne, at, Operand(zero_reg)); |
2086 } | 2083 } |
2087 } | 2084 } |
2088 | 2085 |
2089 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { | 2086 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { |
2090 // spec object -> true. | 2087 // spec object -> true. |
2091 __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 2088 __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
2092 __ Branch(true_label, ge, at, Operand(FIRST_SPEC_OBJECT_TYPE)); | 2089 __ Branch(instr->TrueLabel(chunk_), |
| 2090 ge, at, Operand(FIRST_SPEC_OBJECT_TYPE)); |
2093 } | 2091 } |
2094 | 2092 |
2095 if (expected.Contains(ToBooleanStub::STRING)) { | 2093 if (expected.Contains(ToBooleanStub::STRING)) { |
2096 // String value -> false iff empty. | 2094 // String value -> false iff empty. |
2097 Label not_string; | 2095 Label not_string; |
2098 __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 2096 __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
2099 __ Branch(¬_string, ge , at, Operand(FIRST_NONSTRING_TYPE)); | 2097 __ Branch(¬_string, ge , at, Operand(FIRST_NONSTRING_TYPE)); |
2100 __ lw(at, FieldMemOperand(reg, String::kLengthOffset)); | 2098 __ lw(at, FieldMemOperand(reg, String::kLengthOffset)); |
2101 __ Branch(true_label, ne, at, Operand(zero_reg)); | 2099 __ Branch(instr->TrueLabel(chunk_), ne, at, Operand(zero_reg)); |
2102 __ Branch(false_label); | 2100 __ Branch(instr->FalseLabel(chunk_)); |
2103 __ bind(¬_string); | 2101 __ bind(¬_string); |
2104 } | 2102 } |
2105 | 2103 |
2106 if (expected.Contains(ToBooleanStub::SYMBOL)) { | 2104 if (expected.Contains(ToBooleanStub::SYMBOL)) { |
2107 // Symbol value -> true. | 2105 // Symbol value -> true. |
2108 const Register scratch = scratch1(); | 2106 const Register scratch = scratch1(); |
2109 __ lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 2107 __ lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
2110 __ Branch(true_label, eq, scratch, Operand(SYMBOL_TYPE)); | 2108 __ Branch(instr->TrueLabel(chunk_), eq, scratch, Operand(SYMBOL_TYPE)); |
2111 } | 2109 } |
2112 | 2110 |
2113 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { | 2111 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { |
2114 // heap number -> false iff +0, -0, or NaN. | 2112 // heap number -> false iff +0, -0, or NaN. |
2115 DoubleRegister dbl_scratch = double_scratch0(); | 2113 DoubleRegister dbl_scratch = double_scratch0(); |
2116 Label not_heap_number; | 2114 Label not_heap_number; |
2117 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 2115 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
2118 __ Branch(¬_heap_number, ne, map, Operand(at)); | 2116 __ Branch(¬_heap_number, ne, map, Operand(at)); |
2119 __ ldc1(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); | 2117 __ ldc1(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); |
2120 __ BranchF(true_label, false_label, ne, dbl_scratch, kDoubleRegZero); | 2118 __ BranchF(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), |
| 2119 ne, dbl_scratch, kDoubleRegZero); |
2121 // Falls through if dbl_scratch == 0. | 2120 // Falls through if dbl_scratch == 0. |
2122 __ Branch(false_label); | 2121 __ Branch(instr->FalseLabel(chunk_)); |
2123 __ bind(¬_heap_number); | 2122 __ bind(¬_heap_number); |
2124 } | 2123 } |
2125 | 2124 |
2126 // We've seen something for the first time -> deopt. | 2125 // We've seen something for the first time -> deopt. |
2127 DeoptimizeIf(al, instr->environment(), zero_reg, Operand(zero_reg)); | 2126 DeoptimizeIf(al, instr->environment(), zero_reg, Operand(zero_reg)); |
2128 } | 2127 } |
2129 } | 2128 } |
2130 } | 2129 } |
2131 | 2130 |
2132 | 2131 |
2133 void LCodeGen::EmitGoto(int block) { | 2132 void LCodeGen::EmitGoto(int block) { |
2134 if (!IsNextEmittedBlock(block)) { | 2133 if (!IsNextEmittedBlock(block)) { |
2135 __ jmp(chunk_->GetAssemblyLabel(chunk_->LookupDestination(block))); | 2134 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); |
2136 } | 2135 } |
2137 } | 2136 } |
2138 | 2137 |
2139 | 2138 |
2140 void LCodeGen::DoGoto(LGoto* instr) { | 2139 void LCodeGen::DoGoto(LGoto* instr) { |
2141 EmitGoto(instr->block_id()); | 2140 EmitGoto(instr->block_id()); |
2142 } | 2141 } |
2143 | 2142 |
2144 | 2143 |
2145 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { | 2144 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { |
(...skipping 20 matching lines...) Expand all Loading... |
2166 default: | 2165 default: |
2167 UNREACHABLE(); | 2166 UNREACHABLE(); |
2168 } | 2167 } |
2169 return cond; | 2168 return cond; |
2170 } | 2169 } |
2171 | 2170 |
2172 | 2171 |
2173 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 2172 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
2174 LOperand* left = instr->left(); | 2173 LOperand* left = instr->left(); |
2175 LOperand* right = instr->right(); | 2174 LOperand* right = instr->right(); |
2176 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2177 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2178 | |
2179 Condition cond = TokenToCondition(instr->op(), false); | 2175 Condition cond = TokenToCondition(instr->op(), false); |
2180 | 2176 |
2181 if (left->IsConstantOperand() && right->IsConstantOperand()) { | 2177 if (left->IsConstantOperand() && right->IsConstantOperand()) { |
2182 // We can statically evaluate the comparison. | 2178 // We can statically evaluate the comparison. |
2183 double left_val = ToDouble(LConstantOperand::cast(left)); | 2179 double left_val = ToDouble(LConstantOperand::cast(left)); |
2184 double right_val = ToDouble(LConstantOperand::cast(right)); | 2180 double right_val = ToDouble(LConstantOperand::cast(right)); |
2185 int next_block = | 2181 int next_block = EvalComparison(instr->op(), left_val, right_val) ? |
2186 EvalComparison(instr->op(), left_val, right_val) ? true_block | 2182 instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_); |
2187 : false_block; | |
2188 EmitGoto(next_block); | 2183 EmitGoto(next_block); |
2189 } else { | 2184 } else { |
2190 if (instr->is_double()) { | 2185 if (instr->is_double()) { |
2191 // Compare left and right as doubles and load the | 2186 // Compare left and right as doubles and load the |
2192 // resulting flags into the normal status register. | 2187 // resulting flags into the normal status register. |
2193 FPURegister left_reg = ToDoubleRegister(left); | 2188 FPURegister left_reg = ToDoubleRegister(left); |
2194 FPURegister right_reg = ToDoubleRegister(right); | 2189 FPURegister right_reg = ToDoubleRegister(right); |
2195 | 2190 |
2196 // If a NaN is involved, i.e. the result is unordered, | 2191 // If a NaN is involved, i.e. the result is unordered, |
2197 // jump to false block label. | 2192 // jump to false block label. |
2198 __ BranchF(NULL, chunk_->GetAssemblyLabel(false_block), eq, | 2193 __ BranchF(NULL, instr->FalseLabel(chunk_), eq, |
2199 left_reg, right_reg); | 2194 left_reg, right_reg); |
2200 | 2195 |
2201 EmitBranchF(true_block, false_block, cond, left_reg, right_reg); | 2196 EmitBranchF(instr, cond, left_reg, right_reg); |
2202 } else { | 2197 } else { |
2203 Register cmp_left; | 2198 Register cmp_left; |
2204 Operand cmp_right = Operand(0); | 2199 Operand cmp_right = Operand(0); |
2205 | 2200 |
2206 if (right->IsConstantOperand()) { | 2201 if (right->IsConstantOperand()) { |
2207 int32_t value = ToInteger32(LConstantOperand::cast(right)); | 2202 int32_t value = ToInteger32(LConstantOperand::cast(right)); |
2208 if (instr->hydrogen_value()->representation().IsSmi()) { | 2203 if (instr->hydrogen_value()->representation().IsSmi()) { |
2209 cmp_left = ToRegister(left); | 2204 cmp_left = ToRegister(left); |
2210 cmp_right = Operand(Smi::FromInt(value)); | 2205 cmp_right = Operand(Smi::FromInt(value)); |
2211 } else { | 2206 } else { |
2212 cmp_left = ToRegister(left); | 2207 cmp_left = ToRegister(left); |
2213 cmp_right = Operand(value); | 2208 cmp_right = Operand(value); |
2214 } | 2209 } |
2215 } else if (left->IsConstantOperand()) { | 2210 } else if (left->IsConstantOperand()) { |
2216 int32_t value = ToInteger32(LConstantOperand::cast(left)); | 2211 int32_t value = ToInteger32(LConstantOperand::cast(left)); |
2217 if (instr->hydrogen_value()->representation().IsSmi()) { | 2212 if (instr->hydrogen_value()->representation().IsSmi()) { |
2218 cmp_left = ToRegister(right); | 2213 cmp_left = ToRegister(right); |
2219 cmp_right = Operand(Smi::FromInt(value)); | 2214 cmp_right = Operand(Smi::FromInt(value)); |
2220 } else { | 2215 } else { |
2221 cmp_left = ToRegister(right); | 2216 cmp_left = ToRegister(right); |
2222 cmp_right = Operand(value); | 2217 cmp_right = Operand(value); |
2223 } | 2218 } |
2224 // We transposed the operands. Reverse the condition. | 2219 // We transposed the operands. Reverse the condition. |
2225 cond = ReverseCondition(cond); | 2220 cond = ReverseCondition(cond); |
2226 } else { | 2221 } else { |
2227 cmp_left = ToRegister(left); | 2222 cmp_left = ToRegister(left); |
2228 cmp_right = Operand(ToRegister(right)); | 2223 cmp_right = Operand(ToRegister(right)); |
2229 } | 2224 } |
2230 | 2225 |
2231 EmitBranch(true_block, false_block, cond, cmp_left, cmp_right); | 2226 EmitBranch(instr, cond, cmp_left, cmp_right); |
2232 } | 2227 } |
2233 } | 2228 } |
2234 } | 2229 } |
2235 | 2230 |
2236 | 2231 |
2237 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { | 2232 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { |
2238 Register left = ToRegister(instr->left()); | 2233 Register left = ToRegister(instr->left()); |
2239 Register right = ToRegister(instr->right()); | 2234 Register right = ToRegister(instr->right()); |
2240 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2241 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2242 | 2235 |
2243 EmitBranch(true_block, false_block, eq, left, Operand(right)); | 2236 EmitBranch(instr, eq, left, Operand(right)); |
2244 } | 2237 } |
2245 | 2238 |
2246 | 2239 |
2247 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { | 2240 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { |
2248 Register left = ToRegister(instr->left()); | 2241 Register left = ToRegister(instr->left()); |
2249 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2250 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2251 | 2242 |
2252 EmitBranch(true_block, false_block, eq, left, | 2243 EmitBranch(instr, eq, left, Operand(instr->hydrogen()->right())); |
2253 Operand(instr->hydrogen()->right())); | |
2254 } | 2244 } |
2255 | 2245 |
2256 | 2246 |
2257 Condition LCodeGen::EmitIsObject(Register input, | 2247 Condition LCodeGen::EmitIsObject(Register input, |
2258 Register temp1, | 2248 Register temp1, |
2259 Register temp2, | 2249 Register temp2, |
2260 Label* is_not_object, | 2250 Label* is_not_object, |
2261 Label* is_object) { | 2251 Label* is_object) { |
2262 __ JumpIfSmi(input, is_not_object); | 2252 __ JumpIfSmi(input, is_not_object); |
2263 | 2253 |
(...skipping 14 matching lines...) Expand all Loading... |
2278 | 2268 |
2279 return le; | 2269 return le; |
2280 } | 2270 } |
2281 | 2271 |
2282 | 2272 |
2283 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 2273 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
2284 Register reg = ToRegister(instr->value()); | 2274 Register reg = ToRegister(instr->value()); |
2285 Register temp1 = ToRegister(instr->temp()); | 2275 Register temp1 = ToRegister(instr->temp()); |
2286 Register temp2 = scratch0(); | 2276 Register temp2 = scratch0(); |
2287 | 2277 |
2288 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2278 Condition true_cond = |
2289 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2279 EmitIsObject(reg, temp1, temp2, |
2290 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 2280 instr->FalseLabel(chunk_), instr->TrueLabel(chunk_)); |
2291 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
2292 | 2281 |
2293 Condition true_cond = | 2282 EmitBranch(instr, true_cond, temp2, |
2294 EmitIsObject(reg, temp1, temp2, false_label, true_label); | |
2295 | |
2296 EmitBranch(true_block, false_block, true_cond, temp2, | |
2297 Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 2283 Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
2298 } | 2284 } |
2299 | 2285 |
2300 | 2286 |
2301 Condition LCodeGen::EmitIsString(Register input, | 2287 Condition LCodeGen::EmitIsString(Register input, |
2302 Register temp1, | 2288 Register temp1, |
2303 Label* is_not_string) { | 2289 Label* is_not_string) { |
2304 __ JumpIfSmi(input, is_not_string); | 2290 __ JumpIfSmi(input, is_not_string); |
2305 __ GetObjectType(input, temp1, temp1); | 2291 __ GetObjectType(input, temp1, temp1); |
2306 | 2292 |
2307 return lt; | 2293 return lt; |
2308 } | 2294 } |
2309 | 2295 |
2310 | 2296 |
2311 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { | 2297 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { |
2312 Register reg = ToRegister(instr->value()); | 2298 Register reg = ToRegister(instr->value()); |
2313 Register temp1 = ToRegister(instr->temp()); | 2299 Register temp1 = ToRegister(instr->temp()); |
2314 | 2300 |
2315 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2301 Condition true_cond = |
2316 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2302 EmitIsString(reg, temp1, instr->FalseLabel(chunk_)); |
2317 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
2318 | 2303 |
2319 Condition true_cond = | 2304 EmitBranch(instr, true_cond, temp1, |
2320 EmitIsString(reg, temp1, false_label); | |
2321 | |
2322 EmitBranch(true_block, false_block, true_cond, temp1, | |
2323 Operand(FIRST_NONSTRING_TYPE)); | 2305 Operand(FIRST_NONSTRING_TYPE)); |
2324 } | 2306 } |
2325 | 2307 |
2326 | 2308 |
2327 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 2309 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
2328 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2329 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2330 | |
2331 Register input_reg = EmitLoadRegister(instr->value(), at); | 2310 Register input_reg = EmitLoadRegister(instr->value(), at); |
2332 __ And(at, input_reg, kSmiTagMask); | 2311 __ And(at, input_reg, kSmiTagMask); |
2333 EmitBranch(true_block, false_block, eq, at, Operand(zero_reg)); | 2312 EmitBranch(instr, eq, at, Operand(zero_reg)); |
2334 } | 2313 } |
2335 | 2314 |
2336 | 2315 |
2337 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { | 2316 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { |
2338 Register input = ToRegister(instr->value()); | 2317 Register input = ToRegister(instr->value()); |
2339 Register temp = ToRegister(instr->temp()); | 2318 Register temp = ToRegister(instr->temp()); |
2340 | 2319 |
2341 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2320 __ JumpIfSmi(input, instr->FalseLabel(chunk_)); |
2342 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2343 | |
2344 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); | |
2345 __ lw(temp, FieldMemOperand(input, HeapObject::kMapOffset)); | 2321 __ lw(temp, FieldMemOperand(input, HeapObject::kMapOffset)); |
2346 __ lbu(temp, FieldMemOperand(temp, Map::kBitFieldOffset)); | 2322 __ lbu(temp, FieldMemOperand(temp, Map::kBitFieldOffset)); |
2347 __ And(at, temp, Operand(1 << Map::kIsUndetectable)); | 2323 __ And(at, temp, Operand(1 << Map::kIsUndetectable)); |
2348 EmitBranch(true_block, false_block, ne, at, Operand(zero_reg)); | 2324 EmitBranch(instr, ne, at, Operand(zero_reg)); |
2349 } | 2325 } |
2350 | 2326 |
2351 | 2327 |
2352 static Condition ComputeCompareCondition(Token::Value op) { | 2328 static Condition ComputeCompareCondition(Token::Value op) { |
2353 switch (op) { | 2329 switch (op) { |
2354 case Token::EQ_STRICT: | 2330 case Token::EQ_STRICT: |
2355 case Token::EQ: | 2331 case Token::EQ: |
2356 return eq; | 2332 return eq; |
2357 case Token::LT: | 2333 case Token::LT: |
2358 return lt; | 2334 return lt; |
2359 case Token::GT: | 2335 case Token::GT: |
2360 return gt; | 2336 return gt; |
2361 case Token::LTE: | 2337 case Token::LTE: |
2362 return le; | 2338 return le; |
2363 case Token::GTE: | 2339 case Token::GTE: |
2364 return ge; | 2340 return ge; |
2365 default: | 2341 default: |
2366 UNREACHABLE(); | 2342 UNREACHABLE(); |
2367 return kNoCondition; | 2343 return kNoCondition; |
2368 } | 2344 } |
2369 } | 2345 } |
2370 | 2346 |
2371 | 2347 |
2372 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { | 2348 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { |
2373 Token::Value op = instr->op(); | 2349 Token::Value op = instr->op(); |
2374 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2375 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2376 | 2350 |
2377 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 2351 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
2378 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2352 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2379 | 2353 |
2380 Condition condition = ComputeCompareCondition(op); | 2354 Condition condition = ComputeCompareCondition(op); |
2381 | 2355 |
2382 EmitBranch(true_block, false_block, condition, v0, Operand(zero_reg)); | 2356 EmitBranch(instr, condition, v0, Operand(zero_reg)); |
2383 } | 2357 } |
2384 | 2358 |
2385 | 2359 |
2386 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { | 2360 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { |
2387 InstanceType from = instr->from(); | 2361 InstanceType from = instr->from(); |
2388 InstanceType to = instr->to(); | 2362 InstanceType to = instr->to(); |
2389 if (from == FIRST_TYPE) return to; | 2363 if (from == FIRST_TYPE) return to; |
2390 ASSERT(from == to || to == LAST_TYPE); | 2364 ASSERT(from == to || to == LAST_TYPE); |
2391 return from; | 2365 return from; |
2392 } | 2366 } |
2393 | 2367 |
2394 | 2368 |
2395 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { | 2369 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { |
2396 InstanceType from = instr->from(); | 2370 InstanceType from = instr->from(); |
2397 InstanceType to = instr->to(); | 2371 InstanceType to = instr->to(); |
2398 if (from == to) return eq; | 2372 if (from == to) return eq; |
2399 if (to == LAST_TYPE) return hs; | 2373 if (to == LAST_TYPE) return hs; |
2400 if (from == FIRST_TYPE) return ls; | 2374 if (from == FIRST_TYPE) return ls; |
2401 UNREACHABLE(); | 2375 UNREACHABLE(); |
2402 return eq; | 2376 return eq; |
2403 } | 2377 } |
2404 | 2378 |
2405 | 2379 |
2406 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 2380 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
2407 Register scratch = scratch0(); | 2381 Register scratch = scratch0(); |
2408 Register input = ToRegister(instr->value()); | 2382 Register input = ToRegister(instr->value()); |
2409 | 2383 |
2410 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2384 __ JumpIfSmi(input, instr->FalseLabel(chunk_)); |
2411 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2412 | |
2413 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
2414 | |
2415 __ JumpIfSmi(input, false_label); | |
2416 | 2385 |
2417 __ GetObjectType(input, scratch, scratch); | 2386 __ GetObjectType(input, scratch, scratch); |
2418 EmitBranch(true_block, | 2387 EmitBranch(instr, |
2419 false_block, | |
2420 BranchCondition(instr->hydrogen()), | 2388 BranchCondition(instr->hydrogen()), |
2421 scratch, | 2389 scratch, |
2422 Operand(TestType(instr->hydrogen()))); | 2390 Operand(TestType(instr->hydrogen()))); |
2423 } | 2391 } |
2424 | 2392 |
2425 | 2393 |
2426 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { | 2394 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { |
2427 Register input = ToRegister(instr->value()); | 2395 Register input = ToRegister(instr->value()); |
2428 Register result = ToRegister(instr->result()); | 2396 Register result = ToRegister(instr->result()); |
2429 | 2397 |
2430 __ AssertString(input); | 2398 __ AssertString(input); |
2431 | 2399 |
2432 __ lw(result, FieldMemOperand(input, String::kHashFieldOffset)); | 2400 __ lw(result, FieldMemOperand(input, String::kHashFieldOffset)); |
2433 __ IndexFromHash(result, result); | 2401 __ IndexFromHash(result, result); |
2434 } | 2402 } |
2435 | 2403 |
2436 | 2404 |
2437 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 2405 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
2438 LHasCachedArrayIndexAndBranch* instr) { | 2406 LHasCachedArrayIndexAndBranch* instr) { |
2439 Register input = ToRegister(instr->value()); | 2407 Register input = ToRegister(instr->value()); |
2440 Register scratch = scratch0(); | 2408 Register scratch = scratch0(); |
2441 | 2409 |
2442 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2443 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2444 | |
2445 __ lw(scratch, | 2410 __ lw(scratch, |
2446 FieldMemOperand(input, String::kHashFieldOffset)); | 2411 FieldMemOperand(input, String::kHashFieldOffset)); |
2447 __ And(at, scratch, Operand(String::kContainsCachedArrayIndexMask)); | 2412 __ And(at, scratch, Operand(String::kContainsCachedArrayIndexMask)); |
2448 EmitBranch(true_block, false_block, eq, at, Operand(zero_reg)); | 2413 EmitBranch(instr, eq, at, Operand(zero_reg)); |
2449 } | 2414 } |
2450 | 2415 |
2451 | 2416 |
2452 // Branches to a label or falls through with the answer in flags. Trashes | 2417 // Branches to a label or falls through with the answer in flags. Trashes |
2453 // the temp registers, but not the input. | 2418 // the temp registers, but not the input. |
2454 void LCodeGen::EmitClassOfTest(Label* is_true, | 2419 void LCodeGen::EmitClassOfTest(Label* is_true, |
2455 Label* is_false, | 2420 Label* is_false, |
2456 Handle<String>class_name, | 2421 Handle<String>class_name, |
2457 Register input, | 2422 Register input, |
2458 Register temp, | 2423 Register temp, |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2514 // On MIPS, the caller must do the comparison with Handle<String>class_name. | 2479 // On MIPS, the caller must do the comparison with Handle<String>class_name. |
2515 } | 2480 } |
2516 | 2481 |
2517 | 2482 |
2518 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 2483 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
2519 Register input = ToRegister(instr->value()); | 2484 Register input = ToRegister(instr->value()); |
2520 Register temp = scratch0(); | 2485 Register temp = scratch0(); |
2521 Register temp2 = ToRegister(instr->temp()); | 2486 Register temp2 = ToRegister(instr->temp()); |
2522 Handle<String> class_name = instr->hydrogen()->class_name(); | 2487 Handle<String> class_name = instr->hydrogen()->class_name(); |
2523 | 2488 |
2524 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2489 EmitClassOfTest(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), |
2525 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2490 class_name, input, temp, temp2); |
2526 | 2491 |
2527 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 2492 EmitBranch(instr, eq, temp, Operand(class_name)); |
2528 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
2529 | |
2530 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); | |
2531 | |
2532 EmitBranch(true_block, false_block, eq, temp, Operand(class_name)); | |
2533 } | 2493 } |
2534 | 2494 |
2535 | 2495 |
2536 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 2496 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
2537 Register reg = ToRegister(instr->value()); | 2497 Register reg = ToRegister(instr->value()); |
2538 Register temp = ToRegister(instr->temp()); | 2498 Register temp = ToRegister(instr->temp()); |
2539 int true_block = instr->true_block_id(); | |
2540 int false_block = instr->false_block_id(); | |
2541 | 2499 |
2542 __ lw(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); | 2500 __ lw(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); |
2543 EmitBranch(true_block, false_block, eq, temp, Operand(instr->map())); | 2501 EmitBranch(instr, eq, temp, Operand(instr->map())); |
2544 } | 2502 } |
2545 | 2503 |
2546 | 2504 |
2547 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 2505 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
2548 Label true_label, done; | 2506 Label true_label, done; |
2549 ASSERT(ToRegister(instr->left()).is(a0)); // Object is in a0. | 2507 ASSERT(ToRegister(instr->left()).is(a0)); // Object is in a0. |
2550 ASSERT(ToRegister(instr->right()).is(a1)); // Function is in a1. | 2508 ASSERT(ToRegister(instr->right()).is(a1)); // Function is in a1. |
2551 Register result = ToRegister(instr->result()); | 2509 Register result = ToRegister(instr->result()); |
2552 ASSERT(result.is(v0)); | 2510 ASSERT(result.is(v0)); |
2553 | 2511 |
(...skipping 2973 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5527 void LCodeGen::DoTypeof(LTypeof* instr) { | 5485 void LCodeGen::DoTypeof(LTypeof* instr) { |
5528 ASSERT(ToRegister(instr->result()).is(v0)); | 5486 ASSERT(ToRegister(instr->result()).is(v0)); |
5529 Register input = ToRegister(instr->value()); | 5487 Register input = ToRegister(instr->value()); |
5530 __ push(input); | 5488 __ push(input); |
5531 CallRuntime(Runtime::kTypeof, 1, instr); | 5489 CallRuntime(Runtime::kTypeof, 1, instr); |
5532 } | 5490 } |
5533 | 5491 |
5534 | 5492 |
5535 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 5493 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
5536 Register input = ToRegister(instr->value()); | 5494 Register input = ToRegister(instr->value()); |
5537 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
5538 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
5539 Label* true_label = chunk_->GetAssemblyLabel(true_block); | |
5540 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
5541 | 5495 |
5542 Register cmp1 = no_reg; | 5496 Register cmp1 = no_reg; |
5543 Operand cmp2 = Operand(no_reg); | 5497 Operand cmp2 = Operand(no_reg); |
5544 | 5498 |
5545 Condition final_branch_condition = EmitTypeofIs(true_label, | 5499 Condition final_branch_condition = EmitTypeofIs(instr->TrueLabel(chunk_), |
5546 false_label, | 5500 instr->FalseLabel(chunk_), |
5547 input, | 5501 input, |
5548 instr->type_literal(), | 5502 instr->type_literal(), |
5549 cmp1, | 5503 cmp1, |
5550 cmp2); | 5504 cmp2); |
5551 | 5505 |
5552 ASSERT(cmp1.is_valid()); | 5506 ASSERT(cmp1.is_valid()); |
5553 ASSERT(!cmp2.is_reg() || cmp2.rm().is_valid()); | 5507 ASSERT(!cmp2.is_reg() || cmp2.rm().is_valid()); |
5554 | 5508 |
5555 if (final_branch_condition != kNoCondition) { | 5509 if (final_branch_condition != kNoCondition) { |
5556 EmitBranch(true_block, false_block, final_branch_condition, cmp1, cmp2); | 5510 EmitBranch(instr, final_branch_condition, cmp1, cmp2); |
5557 } | 5511 } |
5558 } | 5512 } |
5559 | 5513 |
5560 | 5514 |
5561 Condition LCodeGen::EmitTypeofIs(Label* true_label, | 5515 Condition LCodeGen::EmitTypeofIs(Label* true_label, |
5562 Label* false_label, | 5516 Label* false_label, |
5563 Register input, | 5517 Register input, |
5564 Handle<String> type_name, | 5518 Handle<String> type_name, |
5565 Register& cmp1, | 5519 Register& cmp1, |
5566 Operand& cmp2) { | 5520 Operand& cmp2) { |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5659 cmp2 = Operand(zero_reg); // Set to valid regs, to avoid caller assertion. | 5613 cmp2 = Operand(zero_reg); // Set to valid regs, to avoid caller assertion. |
5660 __ Branch(false_label); | 5614 __ Branch(false_label); |
5661 } | 5615 } |
5662 | 5616 |
5663 return final_branch_condition; | 5617 return final_branch_condition; |
5664 } | 5618 } |
5665 | 5619 |
5666 | 5620 |
5667 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 5621 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
5668 Register temp1 = ToRegister(instr->temp()); | 5622 Register temp1 = ToRegister(instr->temp()); |
5669 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
5670 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
5671 | 5623 |
5672 EmitIsConstructCall(temp1, scratch0()); | 5624 EmitIsConstructCall(temp1, scratch0()); |
5673 | 5625 |
5674 EmitBranch(true_block, false_block, eq, temp1, | 5626 EmitBranch(instr, eq, temp1, |
5675 Operand(Smi::FromInt(StackFrame::CONSTRUCT))); | 5627 Operand(Smi::FromInt(StackFrame::CONSTRUCT))); |
5676 } | 5628 } |
5677 | 5629 |
5678 | 5630 |
5679 void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) { | 5631 void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) { |
5680 ASSERT(!temp1.is(temp2)); | 5632 ASSERT(!temp1.is(temp2)); |
5681 // Get the frame pointer for the calling frame. | 5633 // Get the frame pointer for the calling frame. |
5682 __ lw(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 5634 __ lw(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
5683 | 5635 |
5684 // Skip the arguments adaptor frame if it exists. | 5636 // Skip the arguments adaptor frame if it exists. |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5922 __ Subu(scratch, result, scratch); | 5874 __ Subu(scratch, result, scratch); |
5923 __ lw(result, FieldMemOperand(scratch, | 5875 __ lw(result, FieldMemOperand(scratch, |
5924 FixedArray::kHeaderSize - kPointerSize)); | 5876 FixedArray::kHeaderSize - kPointerSize)); |
5925 __ bind(&done); | 5877 __ bind(&done); |
5926 } | 5878 } |
5927 | 5879 |
5928 | 5880 |
5929 #undef __ | 5881 #undef __ |
5930 | 5882 |
5931 } } // namespace v8::internal | 5883 } } // namespace v8::internal |
OLD | NEW |