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