| 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 2069 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2080 | 2080 |
| 2081 | 2081 |
| 2082 int LCodeGen::GetNextEmittedBlock() const { | 2082 int LCodeGen::GetNextEmittedBlock() const { |
| 2083 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { | 2083 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { |
| 2084 if (!chunk_->GetLabel(i)->HasReplacement()) return i; | 2084 if (!chunk_->GetLabel(i)->HasReplacement()) return i; |
| 2085 } | 2085 } |
| 2086 return -1; | 2086 return -1; |
| 2087 } | 2087 } |
| 2088 | 2088 |
| 2089 | 2089 |
| 2090 void LCodeGen::EmitBranch(int left_block, int right_block, Condition cc) { | 2090 template<class InstrType> |
| 2091 void LCodeGen::EmitBranch(InstrType instr, Condition cc) { |
| 2092 int right_block = instr->FalseDestination(chunk_); |
| 2093 int left_block = instr->TrueDestination(chunk_); |
| 2094 |
| 2091 int next_block = GetNextEmittedBlock(); | 2095 int next_block = GetNextEmittedBlock(); |
| 2092 right_block = chunk_->LookupDestination(right_block); | |
| 2093 left_block = chunk_->LookupDestination(left_block); | |
| 2094 | 2096 |
| 2095 if (right_block == left_block) { | 2097 if (right_block == left_block) { |
| 2096 EmitGoto(left_block); | 2098 EmitGoto(left_block); |
| 2097 } else if (left_block == next_block) { | 2099 } else if (left_block == next_block) { |
| 2098 __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block)); | 2100 __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block)); |
| 2099 } else if (right_block == next_block) { | 2101 } else if (right_block == next_block) { |
| 2100 __ j(cc, chunk_->GetAssemblyLabel(left_block)); | 2102 __ j(cc, chunk_->GetAssemblyLabel(left_block)); |
| 2101 } else { | 2103 } else { |
| 2102 __ j(cc, chunk_->GetAssemblyLabel(left_block)); | 2104 __ j(cc, chunk_->GetAssemblyLabel(left_block)); |
| 2103 __ jmp(chunk_->GetAssemblyLabel(right_block)); | 2105 __ jmp(chunk_->GetAssemblyLabel(right_block)); |
| 2104 } | 2106 } |
| 2105 } | 2107 } |
| 2106 | 2108 |
| 2107 | 2109 |
| 2108 void LCodeGen::DoBranch(LBranch* instr) { | 2110 void LCodeGen::DoBranch(LBranch* instr) { |
| 2109 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
| 2110 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
| 2111 | |
| 2112 Representation r = instr->hydrogen()->value()->representation(); | 2111 Representation r = instr->hydrogen()->value()->representation(); |
| 2113 if (r.IsSmiOrInteger32()) { | 2112 if (r.IsSmiOrInteger32()) { |
| 2114 ASSERT(!info()->IsStub()); | 2113 ASSERT(!info()->IsStub()); |
| 2115 Register reg = ToRegister(instr->value()); | 2114 Register reg = ToRegister(instr->value()); |
| 2116 __ test(reg, Operand(reg)); | 2115 __ test(reg, Operand(reg)); |
| 2117 EmitBranch(true_block, false_block, not_zero); | 2116 EmitBranch(instr, not_zero); |
| 2118 } else if (r.IsDouble()) { | 2117 } else if (r.IsDouble()) { |
| 2119 ASSERT(!info()->IsStub()); | 2118 ASSERT(!info()->IsStub()); |
| 2120 CpuFeatureScope scope(masm(), SSE2); | 2119 CpuFeatureScope scope(masm(), SSE2); |
| 2121 XMMRegister reg = ToDoubleRegister(instr->value()); | 2120 XMMRegister reg = ToDoubleRegister(instr->value()); |
| 2122 __ xorps(xmm0, xmm0); | 2121 __ xorps(xmm0, xmm0); |
| 2123 __ ucomisd(reg, xmm0); | 2122 __ ucomisd(reg, xmm0); |
| 2124 EmitBranch(true_block, false_block, not_equal); | 2123 EmitBranch(instr, not_equal); |
| 2125 } else { | 2124 } else { |
| 2126 ASSERT(r.IsTagged()); | 2125 ASSERT(r.IsTagged()); |
| 2127 Register reg = ToRegister(instr->value()); | 2126 Register reg = ToRegister(instr->value()); |
| 2128 HType type = instr->hydrogen()->value()->type(); | 2127 HType type = instr->hydrogen()->value()->type(); |
| 2129 if (type.IsBoolean()) { | 2128 if (type.IsBoolean()) { |
| 2130 ASSERT(!info()->IsStub()); | 2129 ASSERT(!info()->IsStub()); |
| 2131 __ cmp(reg, factory()->true_value()); | 2130 __ cmp(reg, factory()->true_value()); |
| 2132 EmitBranch(true_block, false_block, equal); | 2131 EmitBranch(instr, equal); |
| 2133 } else if (type.IsSmi()) { | 2132 } else if (type.IsSmi()) { |
| 2134 ASSERT(!info()->IsStub()); | 2133 ASSERT(!info()->IsStub()); |
| 2135 __ test(reg, Operand(reg)); | 2134 __ test(reg, Operand(reg)); |
| 2136 EmitBranch(true_block, false_block, not_equal); | 2135 EmitBranch(instr, not_equal); |
| 2137 } else { | 2136 } else { |
| 2138 Label* true_label = chunk_->GetAssemblyLabel(true_block); | |
| 2139 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
| 2140 | |
| 2141 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); | 2137 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); |
| 2142 // Avoid deopts in the case where we've never executed this path before. | 2138 // Avoid deopts in the case where we've never executed this path before. |
| 2143 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); | 2139 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); |
| 2144 | 2140 |
| 2145 if (expected.Contains(ToBooleanStub::UNDEFINED)) { | 2141 if (expected.Contains(ToBooleanStub::UNDEFINED)) { |
| 2146 // undefined -> false. | 2142 // undefined -> false. |
| 2147 __ cmp(reg, factory()->undefined_value()); | 2143 __ cmp(reg, factory()->undefined_value()); |
| 2148 __ j(equal, false_label); | 2144 __ j(equal, instr->FalseLabel(chunk_)); |
| 2149 } | 2145 } |
| 2150 if (expected.Contains(ToBooleanStub::BOOLEAN)) { | 2146 if (expected.Contains(ToBooleanStub::BOOLEAN)) { |
| 2151 // true -> true. | 2147 // true -> true. |
| 2152 __ cmp(reg, factory()->true_value()); | 2148 __ cmp(reg, factory()->true_value()); |
| 2153 __ j(equal, true_label); | 2149 __ j(equal, instr->TrueLabel(chunk_)); |
| 2154 // false -> false. | 2150 // false -> false. |
| 2155 __ cmp(reg, factory()->false_value()); | 2151 __ cmp(reg, factory()->false_value()); |
| 2156 __ j(equal, false_label); | 2152 __ j(equal, instr->FalseLabel(chunk_)); |
| 2157 } | 2153 } |
| 2158 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { | 2154 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { |
| 2159 // 'null' -> false. | 2155 // 'null' -> false. |
| 2160 __ cmp(reg, factory()->null_value()); | 2156 __ cmp(reg, factory()->null_value()); |
| 2161 __ j(equal, false_label); | 2157 __ j(equal, instr->FalseLabel(chunk_)); |
| 2162 } | 2158 } |
| 2163 | 2159 |
| 2164 if (expected.Contains(ToBooleanStub::SMI)) { | 2160 if (expected.Contains(ToBooleanStub::SMI)) { |
| 2165 // Smis: 0 -> false, all other -> true. | 2161 // Smis: 0 -> false, all other -> true. |
| 2166 __ test(reg, Operand(reg)); | 2162 __ test(reg, Operand(reg)); |
| 2167 __ j(equal, false_label); | 2163 __ j(equal, instr->FalseLabel(chunk_)); |
| 2168 __ JumpIfSmi(reg, true_label); | 2164 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
| 2169 } else if (expected.NeedsMap()) { | 2165 } else if (expected.NeedsMap()) { |
| 2170 // If we need a map later and have a Smi -> deopt. | 2166 // If we need a map later and have a Smi -> deopt. |
| 2171 __ test(reg, Immediate(kSmiTagMask)); | 2167 __ test(reg, Immediate(kSmiTagMask)); |
| 2172 DeoptimizeIf(zero, instr->environment()); | 2168 DeoptimizeIf(zero, instr->environment()); |
| 2173 } | 2169 } |
| 2174 | 2170 |
| 2175 Register map = no_reg; // Keep the compiler happy. | 2171 Register map = no_reg; // Keep the compiler happy. |
| 2176 if (expected.NeedsMap()) { | 2172 if (expected.NeedsMap()) { |
| 2177 map = ToRegister(instr->temp()); | 2173 map = ToRegister(instr->temp()); |
| 2178 ASSERT(!map.is(reg)); | 2174 ASSERT(!map.is(reg)); |
| 2179 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); | 2175 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); |
| 2180 | 2176 |
| 2181 if (expected.CanBeUndetectable()) { | 2177 if (expected.CanBeUndetectable()) { |
| 2182 // Undetectable -> false. | 2178 // Undetectable -> false. |
| 2183 __ test_b(FieldOperand(map, Map::kBitFieldOffset), | 2179 __ test_b(FieldOperand(map, Map::kBitFieldOffset), |
| 2184 1 << Map::kIsUndetectable); | 2180 1 << Map::kIsUndetectable); |
| 2185 __ j(not_zero, false_label); | 2181 __ j(not_zero, instr->FalseLabel(chunk_)); |
| 2186 } | 2182 } |
| 2187 } | 2183 } |
| 2188 | 2184 |
| 2189 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { | 2185 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { |
| 2190 // spec object -> true. | 2186 // spec object -> true. |
| 2191 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); | 2187 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); |
| 2192 __ j(above_equal, true_label); | 2188 __ j(above_equal, instr->TrueLabel(chunk_)); |
| 2193 } | 2189 } |
| 2194 | 2190 |
| 2195 if (expected.Contains(ToBooleanStub::STRING)) { | 2191 if (expected.Contains(ToBooleanStub::STRING)) { |
| 2196 // String value -> false iff empty. | 2192 // String value -> false iff empty. |
| 2197 Label not_string; | 2193 Label not_string; |
| 2198 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); | 2194 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); |
| 2199 __ j(above_equal, ¬_string, Label::kNear); | 2195 __ j(above_equal, ¬_string, Label::kNear); |
| 2200 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); | 2196 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); |
| 2201 __ j(not_zero, true_label); | 2197 __ j(not_zero, instr->TrueLabel(chunk_)); |
| 2202 __ jmp(false_label); | 2198 __ jmp(instr->FalseLabel(chunk_)); |
| 2203 __ bind(¬_string); | 2199 __ bind(¬_string); |
| 2204 } | 2200 } |
| 2205 | 2201 |
| 2206 if (expected.Contains(ToBooleanStub::SYMBOL)) { | 2202 if (expected.Contains(ToBooleanStub::SYMBOL)) { |
| 2207 // Symbol value -> true. | 2203 // Symbol value -> true. |
| 2208 __ CmpInstanceType(map, SYMBOL_TYPE); | 2204 __ CmpInstanceType(map, SYMBOL_TYPE); |
| 2209 __ j(equal, true_label); | 2205 __ j(equal, instr->TrueLabel(chunk_)); |
| 2210 } | 2206 } |
| 2211 | 2207 |
| 2212 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { | 2208 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { |
| 2213 // heap number -> false iff +0, -0, or NaN. | 2209 // heap number -> false iff +0, -0, or NaN. |
| 2214 Label not_heap_number; | 2210 Label not_heap_number; |
| 2215 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 2211 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 2216 factory()->heap_number_map()); | 2212 factory()->heap_number_map()); |
| 2217 __ j(not_equal, ¬_heap_number, Label::kNear); | 2213 __ j(not_equal, ¬_heap_number, Label::kNear); |
| 2218 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { | 2214 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
| 2219 CpuFeatureScope scope(masm(), SSE2); | 2215 CpuFeatureScope scope(masm(), SSE2); |
| 2220 __ xorps(xmm0, xmm0); | 2216 __ xorps(xmm0, xmm0); |
| 2221 __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset)); | 2217 __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset)); |
| 2222 } else { | 2218 } else { |
| 2223 __ fldz(); | 2219 __ fldz(); |
| 2224 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); | 2220 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); |
| 2225 __ FCmp(); | 2221 __ FCmp(); |
| 2226 } | 2222 } |
| 2227 __ j(zero, false_label); | 2223 __ j(zero, instr->FalseLabel(chunk_)); |
| 2228 __ jmp(true_label); | 2224 __ jmp(instr->TrueLabel(chunk_)); |
| 2229 __ bind(¬_heap_number); | 2225 __ bind(¬_heap_number); |
| 2230 } | 2226 } |
| 2231 | 2227 |
| 2232 // We've seen something for the first time -> deopt. | 2228 // We've seen something for the first time -> deopt. |
| 2233 DeoptimizeIf(no_condition, instr->environment()); | 2229 DeoptimizeIf(no_condition, instr->environment()); |
| 2234 } | 2230 } |
| 2235 } | 2231 } |
| 2236 } | 2232 } |
| 2237 | 2233 |
| 2238 | 2234 |
| 2239 void LCodeGen::EmitGoto(int block) { | 2235 void LCodeGen::EmitGoto(int block) { |
| 2240 if (!IsNextEmittedBlock(block)) { | 2236 if (!IsNextEmittedBlock(block)) { |
| 2241 __ jmp(chunk_->GetAssemblyLabel(chunk_->LookupDestination(block))); | 2237 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); |
| 2242 } | 2238 } |
| 2243 } | 2239 } |
| 2244 | 2240 |
| 2245 | 2241 |
| 2246 void LCodeGen::DoGoto(LGoto* instr) { | 2242 void LCodeGen::DoGoto(LGoto* instr) { |
| 2247 EmitGoto(instr->block_id()); | 2243 EmitGoto(instr->block_id()); |
| 2248 } | 2244 } |
| 2249 | 2245 |
| 2250 | 2246 |
| 2251 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { | 2247 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2272 default: | 2268 default: |
| 2273 UNREACHABLE(); | 2269 UNREACHABLE(); |
| 2274 } | 2270 } |
| 2275 return cond; | 2271 return cond; |
| 2276 } | 2272 } |
| 2277 | 2273 |
| 2278 | 2274 |
| 2279 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 2275 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
| 2280 LOperand* left = instr->left(); | 2276 LOperand* left = instr->left(); |
| 2281 LOperand* right = instr->right(); | 2277 LOperand* right = instr->right(); |
| 2282 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
| 2283 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
| 2284 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | 2278 Condition cc = TokenToCondition(instr->op(), instr->is_double()); |
| 2285 | 2279 |
| 2286 if (left->IsConstantOperand() && right->IsConstantOperand()) { | 2280 if (left->IsConstantOperand() && right->IsConstantOperand()) { |
| 2287 // We can statically evaluate the comparison. | 2281 // We can statically evaluate the comparison. |
| 2288 double left_val = ToDouble(LConstantOperand::cast(left)); | 2282 double left_val = ToDouble(LConstantOperand::cast(left)); |
| 2289 double right_val = ToDouble(LConstantOperand::cast(right)); | 2283 double right_val = ToDouble(LConstantOperand::cast(right)); |
| 2290 int next_block = | 2284 int next_block = EvalComparison(instr->op(), left_val, right_val) ? |
| 2291 EvalComparison(instr->op(), left_val, right_val) ? true_block | 2285 instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_); |
| 2292 : false_block; | |
| 2293 EmitGoto(next_block); | 2286 EmitGoto(next_block); |
| 2294 } else { | 2287 } else { |
| 2295 if (instr->is_double()) { | 2288 if (instr->is_double()) { |
| 2296 CpuFeatureScope scope(masm(), SSE2); | 2289 CpuFeatureScope scope(masm(), SSE2); |
| 2297 // Don't base result on EFLAGS when a NaN is involved. Instead | 2290 // Don't base result on EFLAGS when a NaN is involved. Instead |
| 2298 // jump to the false block. | 2291 // jump to the false block. |
| 2299 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); | 2292 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); |
| 2300 __ j(parity_even, chunk_->GetAssemblyLabel(false_block)); | 2293 __ j(parity_even, instr->FalseLabel(chunk_)); |
| 2301 } else { | 2294 } else { |
| 2302 if (right->IsConstantOperand()) { | 2295 if (right->IsConstantOperand()) { |
| 2303 int32_t const_value = ToInteger32(LConstantOperand::cast(right)); | 2296 int32_t const_value = ToInteger32(LConstantOperand::cast(right)); |
| 2304 if (instr->hydrogen_value()->representation().IsSmi()) { | 2297 if (instr->hydrogen_value()->representation().IsSmi()) { |
| 2305 __ cmp(ToOperand(left), Immediate(Smi::FromInt(const_value))); | 2298 __ cmp(ToOperand(left), Immediate(Smi::FromInt(const_value))); |
| 2306 } else { | 2299 } else { |
| 2307 __ cmp(ToOperand(left), Immediate(const_value)); | 2300 __ cmp(ToOperand(left), Immediate(const_value)); |
| 2308 } | 2301 } |
| 2309 } else if (left->IsConstantOperand()) { | 2302 } else if (left->IsConstantOperand()) { |
| 2310 int32_t const_value = ToInteger32(LConstantOperand::cast(left)); | 2303 int32_t const_value = ToInteger32(LConstantOperand::cast(left)); |
| 2311 if (instr->hydrogen_value()->representation().IsSmi()) { | 2304 if (instr->hydrogen_value()->representation().IsSmi()) { |
| 2312 __ cmp(ToOperand(right), Immediate(Smi::FromInt(const_value))); | 2305 __ cmp(ToOperand(right), Immediate(Smi::FromInt(const_value))); |
| 2313 } else { | 2306 } else { |
| 2314 __ cmp(ToOperand(right), Immediate(const_value)); | 2307 __ cmp(ToOperand(right), Immediate(const_value)); |
| 2315 } | 2308 } |
| 2316 // We transposed the operands. Reverse the condition. | 2309 // We transposed the operands. Reverse the condition. |
| 2317 cc = ReverseCondition(cc); | 2310 cc = ReverseCondition(cc); |
| 2318 } else { | 2311 } else { |
| 2319 __ cmp(ToRegister(left), ToOperand(right)); | 2312 __ cmp(ToRegister(left), ToOperand(right)); |
| 2320 } | 2313 } |
| 2321 } | 2314 } |
| 2322 EmitBranch(true_block, false_block, cc); | 2315 EmitBranch(instr, cc); |
| 2323 } | 2316 } |
| 2324 } | 2317 } |
| 2325 | 2318 |
| 2326 | 2319 |
| 2327 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { | 2320 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { |
| 2328 Register left = ToRegister(instr->left()); | 2321 Register left = ToRegister(instr->left()); |
| 2329 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
| 2330 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
| 2331 | 2322 |
| 2332 if (instr->right()->IsConstantOperand()) { | 2323 if (instr->right()->IsConstantOperand()) { |
| 2333 Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right())); | 2324 Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right())); |
| 2334 __ CmpObject(left, right); | 2325 __ CmpObject(left, right); |
| 2335 } else { | 2326 } else { |
| 2336 Operand right = ToOperand(instr->right()); | 2327 Operand right = ToOperand(instr->right()); |
| 2337 __ cmp(left, right); | 2328 __ cmp(left, right); |
| 2338 } | 2329 } |
| 2339 EmitBranch(true_block, false_block, equal); | 2330 EmitBranch(instr, equal); |
| 2340 } | 2331 } |
| 2341 | 2332 |
| 2342 | 2333 |
| 2343 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { | 2334 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { |
| 2344 Register left = ToRegister(instr->left()); | 2335 Register left = ToRegister(instr->left()); |
| 2345 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
| 2346 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
| 2347 | 2336 |
| 2348 __ cmp(left, instr->hydrogen()->right()); | 2337 __ cmp(left, instr->hydrogen()->right()); |
| 2349 EmitBranch(true_block, false_block, equal); | 2338 EmitBranch(instr, equal); |
| 2350 } | 2339 } |
| 2351 | 2340 |
| 2352 | 2341 |
| 2353 Condition LCodeGen::EmitIsObject(Register input, | 2342 Condition LCodeGen::EmitIsObject(Register input, |
| 2354 Register temp1, | 2343 Register temp1, |
| 2355 Label* is_not_object, | 2344 Label* is_not_object, |
| 2356 Label* is_object) { | 2345 Label* is_object) { |
| 2357 __ JumpIfSmi(input, is_not_object); | 2346 __ JumpIfSmi(input, is_not_object); |
| 2358 | 2347 |
| 2359 __ cmp(input, isolate()->factory()->null_value()); | 2348 __ cmp(input, isolate()->factory()->null_value()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2370 __ j(below, is_not_object); | 2359 __ j(below, is_not_object); |
| 2371 __ cmp(temp1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); | 2360 __ cmp(temp1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
| 2372 return below_equal; | 2361 return below_equal; |
| 2373 } | 2362 } |
| 2374 | 2363 |
| 2375 | 2364 |
| 2376 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 2365 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
| 2377 Register reg = ToRegister(instr->value()); | 2366 Register reg = ToRegister(instr->value()); |
| 2378 Register temp = ToRegister(instr->temp()); | 2367 Register temp = ToRegister(instr->temp()); |
| 2379 | 2368 |
| 2380 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2369 Condition true_cond = EmitIsObject( |
| 2381 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2370 reg, temp, instr->FalseLabel(chunk_), instr->TrueLabel(chunk_)); |
| 2382 Label* true_label = chunk_->GetAssemblyLabel(true_block); | |
| 2383 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
| 2384 | 2371 |
| 2385 Condition true_cond = EmitIsObject(reg, temp, false_label, true_label); | 2372 EmitBranch(instr, true_cond); |
| 2386 | |
| 2387 EmitBranch(true_block, false_block, true_cond); | |
| 2388 } | 2373 } |
| 2389 | 2374 |
| 2390 | 2375 |
| 2391 Condition LCodeGen::EmitIsString(Register input, | 2376 Condition LCodeGen::EmitIsString(Register input, |
| 2392 Register temp1, | 2377 Register temp1, |
| 2393 Label* is_not_string) { | 2378 Label* is_not_string) { |
| 2394 __ JumpIfSmi(input, is_not_string); | 2379 __ JumpIfSmi(input, is_not_string); |
| 2395 | 2380 |
| 2396 Condition cond = masm_->IsObjectStringType(input, temp1, temp1); | 2381 Condition cond = masm_->IsObjectStringType(input, temp1, temp1); |
| 2397 | 2382 |
| 2398 return cond; | 2383 return cond; |
| 2399 } | 2384 } |
| 2400 | 2385 |
| 2401 | 2386 |
| 2402 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { | 2387 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { |
| 2403 Register reg = ToRegister(instr->value()); | 2388 Register reg = ToRegister(instr->value()); |
| 2404 Register temp = ToRegister(instr->temp()); | 2389 Register temp = ToRegister(instr->temp()); |
| 2405 | 2390 |
| 2406 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2391 Condition true_cond = EmitIsString(reg, temp, instr->FalseLabel(chunk_)); |
| 2407 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
| 2408 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
| 2409 | 2392 |
| 2410 Condition true_cond = EmitIsString(reg, temp, false_label); | 2393 EmitBranch(instr, true_cond); |
| 2411 | |
| 2412 EmitBranch(true_block, false_block, true_cond); | |
| 2413 } | 2394 } |
| 2414 | 2395 |
| 2415 | 2396 |
| 2416 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 2397 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
| 2417 Operand input = ToOperand(instr->value()); | 2398 Operand input = ToOperand(instr->value()); |
| 2418 | 2399 |
| 2419 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
| 2420 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
| 2421 | |
| 2422 __ test(input, Immediate(kSmiTagMask)); | 2400 __ test(input, Immediate(kSmiTagMask)); |
| 2423 EmitBranch(true_block, false_block, zero); | 2401 EmitBranch(instr, zero); |
| 2424 } | 2402 } |
| 2425 | 2403 |
| 2426 | 2404 |
| 2427 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { | 2405 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { |
| 2428 Register input = ToRegister(instr->value()); | 2406 Register input = ToRegister(instr->value()); |
| 2429 Register temp = ToRegister(instr->temp()); | 2407 Register temp = ToRegister(instr->temp()); |
| 2430 | 2408 |
| 2431 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
| 2432 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
| 2433 | |
| 2434 STATIC_ASSERT(kSmiTag == 0); | 2409 STATIC_ASSERT(kSmiTag == 0); |
| 2435 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); | 2410 __ JumpIfSmi(input, instr->FalseLabel(chunk_)); |
| 2436 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); | 2411 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); |
| 2437 __ test_b(FieldOperand(temp, Map::kBitFieldOffset), | 2412 __ test_b(FieldOperand(temp, Map::kBitFieldOffset), |
| 2438 1 << Map::kIsUndetectable); | 2413 1 << Map::kIsUndetectable); |
| 2439 EmitBranch(true_block, false_block, not_zero); | 2414 EmitBranch(instr, not_zero); |
| 2440 } | 2415 } |
| 2441 | 2416 |
| 2442 | 2417 |
| 2443 static Condition ComputeCompareCondition(Token::Value op) { | 2418 static Condition ComputeCompareCondition(Token::Value op) { |
| 2444 switch (op) { | 2419 switch (op) { |
| 2445 case Token::EQ_STRICT: | 2420 case Token::EQ_STRICT: |
| 2446 case Token::EQ: | 2421 case Token::EQ: |
| 2447 return equal; | 2422 return equal; |
| 2448 case Token::LT: | 2423 case Token::LT: |
| 2449 return less; | 2424 return less; |
| 2450 case Token::GT: | 2425 case Token::GT: |
| 2451 return greater; | 2426 return greater; |
| 2452 case Token::LTE: | 2427 case Token::LTE: |
| 2453 return less_equal; | 2428 return less_equal; |
| 2454 case Token::GTE: | 2429 case Token::GTE: |
| 2455 return greater_equal; | 2430 return greater_equal; |
| 2456 default: | 2431 default: |
| 2457 UNREACHABLE(); | 2432 UNREACHABLE(); |
| 2458 return no_condition; | 2433 return no_condition; |
| 2459 } | 2434 } |
| 2460 } | 2435 } |
| 2461 | 2436 |
| 2462 | 2437 |
| 2463 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { | 2438 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { |
| 2464 Token::Value op = instr->op(); | 2439 Token::Value op = instr->op(); |
| 2465 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
| 2466 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
| 2467 | 2440 |
| 2468 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 2441 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
| 2469 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2442 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2470 | 2443 |
| 2471 Condition condition = ComputeCompareCondition(op); | 2444 Condition condition = ComputeCompareCondition(op); |
| 2472 __ test(eax, Operand(eax)); | 2445 __ test(eax, Operand(eax)); |
| 2473 | 2446 |
| 2474 EmitBranch(true_block, false_block, condition); | 2447 EmitBranch(instr, condition); |
| 2475 } | 2448 } |
| 2476 | 2449 |
| 2477 | 2450 |
| 2478 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { | 2451 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { |
| 2479 InstanceType from = instr->from(); | 2452 InstanceType from = instr->from(); |
| 2480 InstanceType to = instr->to(); | 2453 InstanceType to = instr->to(); |
| 2481 if (from == FIRST_TYPE) return to; | 2454 if (from == FIRST_TYPE) return to; |
| 2482 ASSERT(from == to || to == LAST_TYPE); | 2455 ASSERT(from == to || to == LAST_TYPE); |
| 2483 return from; | 2456 return from; |
| 2484 } | 2457 } |
| 2485 | 2458 |
| 2486 | 2459 |
| 2487 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { | 2460 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { |
| 2488 InstanceType from = instr->from(); | 2461 InstanceType from = instr->from(); |
| 2489 InstanceType to = instr->to(); | 2462 InstanceType to = instr->to(); |
| 2490 if (from == to) return equal; | 2463 if (from == to) return equal; |
| 2491 if (to == LAST_TYPE) return above_equal; | 2464 if (to == LAST_TYPE) return above_equal; |
| 2492 if (from == FIRST_TYPE) return below_equal; | 2465 if (from == FIRST_TYPE) return below_equal; |
| 2493 UNREACHABLE(); | 2466 UNREACHABLE(); |
| 2494 return equal; | 2467 return equal; |
| 2495 } | 2468 } |
| 2496 | 2469 |
| 2497 | 2470 |
| 2498 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 2471 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
| 2499 Register input = ToRegister(instr->value()); | 2472 Register input = ToRegister(instr->value()); |
| 2500 Register temp = ToRegister(instr->temp()); | 2473 Register temp = ToRegister(instr->temp()); |
| 2501 | 2474 |
| 2502 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2475 __ JumpIfSmi(input, instr->FalseLabel(chunk_)); |
| 2503 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
| 2504 | |
| 2505 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
| 2506 | |
| 2507 __ JumpIfSmi(input, false_label); | |
| 2508 | 2476 |
| 2509 __ CmpObjectType(input, TestType(instr->hydrogen()), temp); | 2477 __ CmpObjectType(input, TestType(instr->hydrogen()), temp); |
| 2510 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); | 2478 EmitBranch(instr, BranchCondition(instr->hydrogen())); |
| 2511 } | 2479 } |
| 2512 | 2480 |
| 2513 | 2481 |
| 2514 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { | 2482 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { |
| 2515 Register input = ToRegister(instr->value()); | 2483 Register input = ToRegister(instr->value()); |
| 2516 Register result = ToRegister(instr->result()); | 2484 Register result = ToRegister(instr->result()); |
| 2517 | 2485 |
| 2518 __ AssertString(input); | 2486 __ AssertString(input); |
| 2519 | 2487 |
| 2520 __ mov(result, FieldOperand(input, String::kHashFieldOffset)); | 2488 __ mov(result, FieldOperand(input, String::kHashFieldOffset)); |
| 2521 __ IndexFromHash(result, result); | 2489 __ IndexFromHash(result, result); |
| 2522 } | 2490 } |
| 2523 | 2491 |
| 2524 | 2492 |
| 2525 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 2493 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
| 2526 LHasCachedArrayIndexAndBranch* instr) { | 2494 LHasCachedArrayIndexAndBranch* instr) { |
| 2527 Register input = ToRegister(instr->value()); | 2495 Register input = ToRegister(instr->value()); |
| 2528 | 2496 |
| 2529 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
| 2530 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
| 2531 | |
| 2532 __ test(FieldOperand(input, String::kHashFieldOffset), | 2497 __ test(FieldOperand(input, String::kHashFieldOffset), |
| 2533 Immediate(String::kContainsCachedArrayIndexMask)); | 2498 Immediate(String::kContainsCachedArrayIndexMask)); |
| 2534 EmitBranch(true_block, false_block, equal); | 2499 EmitBranch(instr, equal); |
| 2535 } | 2500 } |
| 2536 | 2501 |
| 2537 | 2502 |
| 2538 // Branches to a label or falls through with the answer in the z flag. Trashes | 2503 // Branches to a label or falls through with the answer in the z flag. Trashes |
| 2539 // the temp registers, but not the input. | 2504 // the temp registers, but not the input. |
| 2540 void LCodeGen::EmitClassOfTest(Label* is_true, | 2505 void LCodeGen::EmitClassOfTest(Label* is_true, |
| 2541 Label* is_false, | 2506 Label* is_false, |
| 2542 Handle<String>class_name, | 2507 Handle<String>class_name, |
| 2543 Register input, | 2508 Register input, |
| 2544 Register temp, | 2509 Register temp, |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2600 } | 2565 } |
| 2601 | 2566 |
| 2602 | 2567 |
| 2603 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 2568 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
| 2604 Register input = ToRegister(instr->value()); | 2569 Register input = ToRegister(instr->value()); |
| 2605 Register temp = ToRegister(instr->temp()); | 2570 Register temp = ToRegister(instr->temp()); |
| 2606 Register temp2 = ToRegister(instr->temp2()); | 2571 Register temp2 = ToRegister(instr->temp2()); |
| 2607 | 2572 |
| 2608 Handle<String> class_name = instr->hydrogen()->class_name(); | 2573 Handle<String> class_name = instr->hydrogen()->class_name(); |
| 2609 | 2574 |
| 2610 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2575 EmitClassOfTest(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), |
| 2611 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2576 class_name, input, temp, temp2); |
| 2612 | 2577 |
| 2613 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 2578 EmitBranch(instr, equal); |
| 2614 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
| 2615 | |
| 2616 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); | |
| 2617 | |
| 2618 EmitBranch(true_block, false_block, equal); | |
| 2619 } | 2579 } |
| 2620 | 2580 |
| 2621 | 2581 |
| 2622 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 2582 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
| 2623 Register reg = ToRegister(instr->value()); | 2583 Register reg = ToRegister(instr->value()); |
| 2624 int true_block = instr->true_block_id(); | |
| 2625 int false_block = instr->false_block_id(); | |
| 2626 | |
| 2627 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); | 2584 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); |
| 2628 EmitBranch(true_block, false_block, equal); | 2585 EmitBranch(instr, equal); |
| 2629 } | 2586 } |
| 2630 | 2587 |
| 2631 | 2588 |
| 2632 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 2589 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
| 2633 // Object and function are in fixed registers defined by the stub. | 2590 // Object and function are in fixed registers defined by the stub. |
| 2634 ASSERT(ToRegister(instr->context()).is(esi)); | 2591 ASSERT(ToRegister(instr->context()).is(esi)); |
| 2635 InstanceofStub stub(InstanceofStub::kArgsInRegisters); | 2592 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
| 2636 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 2593 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 2637 | 2594 |
| 2638 Label true_value, done; | 2595 Label true_value, done; |
| (...skipping 3508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6147 | 6104 |
| 6148 void LCodeGen::DoTypeof(LTypeof* instr) { | 6105 void LCodeGen::DoTypeof(LTypeof* instr) { |
| 6149 LOperand* input = instr->value(); | 6106 LOperand* input = instr->value(); |
| 6150 EmitPushTaggedOperand(input); | 6107 EmitPushTaggedOperand(input); |
| 6151 CallRuntime(Runtime::kTypeof, 1, instr); | 6108 CallRuntime(Runtime::kTypeof, 1, instr); |
| 6152 } | 6109 } |
| 6153 | 6110 |
| 6154 | 6111 |
| 6155 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 6112 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
| 6156 Register input = ToRegister(instr->value()); | 6113 Register input = ToRegister(instr->value()); |
| 6157 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
| 6158 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
| 6159 Label* true_label = chunk_->GetAssemblyLabel(true_block); | |
| 6160 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
| 6161 | 6114 |
| 6162 Condition final_branch_condition = | 6115 Condition final_branch_condition = |
| 6163 EmitTypeofIs(true_label, false_label, input, instr->type_literal()); | 6116 EmitTypeofIs(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), |
| 6117 input, instr->type_literal()); |
| 6164 if (final_branch_condition != no_condition) { | 6118 if (final_branch_condition != no_condition) { |
| 6165 EmitBranch(true_block, false_block, final_branch_condition); | 6119 EmitBranch(instr, final_branch_condition); |
| 6166 } | 6120 } |
| 6167 } | 6121 } |
| 6168 | 6122 |
| 6169 | 6123 |
| 6170 Condition LCodeGen::EmitTypeofIs(Label* true_label, | 6124 Condition LCodeGen::EmitTypeofIs(Label* true_label, |
| 6171 Label* false_label, | 6125 Label* false_label, |
| 6172 Register input, | 6126 Register input, |
| 6173 Handle<String> type_name) { | 6127 Handle<String> type_name) { |
| 6174 Condition final_branch_condition = no_condition; | 6128 Condition final_branch_condition = no_condition; |
| 6175 if (type_name->Equals(heap()->number_string())) { | 6129 if (type_name->Equals(heap()->number_string())) { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6236 | 6190 |
| 6237 } else { | 6191 } else { |
| 6238 __ jmp(false_label); | 6192 __ jmp(false_label); |
| 6239 } | 6193 } |
| 6240 return final_branch_condition; | 6194 return final_branch_condition; |
| 6241 } | 6195 } |
| 6242 | 6196 |
| 6243 | 6197 |
| 6244 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 6198 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
| 6245 Register temp = ToRegister(instr->temp()); | 6199 Register temp = ToRegister(instr->temp()); |
| 6246 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
| 6247 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
| 6248 | 6200 |
| 6249 EmitIsConstructCall(temp); | 6201 EmitIsConstructCall(temp); |
| 6250 EmitBranch(true_block, false_block, equal); | 6202 EmitBranch(instr, equal); |
| 6251 } | 6203 } |
| 6252 | 6204 |
| 6253 | 6205 |
| 6254 void LCodeGen::EmitIsConstructCall(Register temp) { | 6206 void LCodeGen::EmitIsConstructCall(Register temp) { |
| 6255 // Get the frame pointer for the calling frame. | 6207 // Get the frame pointer for the calling frame. |
| 6256 __ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 6208 __ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| 6257 | 6209 |
| 6258 // Skip the arguments adaptor frame if it exists. | 6210 // Skip the arguments adaptor frame if it exists. |
| 6259 Label check_frame_marker; | 6211 Label check_frame_marker; |
| 6260 __ cmp(Operand(temp, StandardFrameConstants::kContextOffset), | 6212 __ cmp(Operand(temp, StandardFrameConstants::kContextOffset), |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6504 FixedArray::kHeaderSize - kPointerSize)); | 6456 FixedArray::kHeaderSize - kPointerSize)); |
| 6505 __ bind(&done); | 6457 __ bind(&done); |
| 6506 } | 6458 } |
| 6507 | 6459 |
| 6508 | 6460 |
| 6509 #undef __ | 6461 #undef __ |
| 6510 | 6462 |
| 6511 } } // namespace v8::internal | 6463 } } // namespace v8::internal |
| 6512 | 6464 |
| 6513 #endif // V8_TARGET_ARCH_IA32 | 6465 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |