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 2141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2152 } | 2152 } |
2153 | 2153 |
2154 | 2154 |
2155 int LCodeGen::GetNextEmittedBlock() const { | 2155 int LCodeGen::GetNextEmittedBlock() const { |
2156 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { | 2156 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { |
2157 if (!chunk_->GetLabel(i)->HasReplacement()) return i; | 2157 if (!chunk_->GetLabel(i)->HasReplacement()) return i; |
2158 } | 2158 } |
2159 return -1; | 2159 return -1; |
2160 } | 2160 } |
2161 | 2161 |
| 2162 template<class InstrType> |
| 2163 void LCodeGen::EmitBranch(InstrType instr, Condition cc) { |
| 2164 int right_block = instr->FalseDestination(chunk_); |
| 2165 int left_block = instr->TrueDestination(chunk_); |
2162 | 2166 |
2163 void LCodeGen::EmitBranch(int left_block, int right_block, Condition cc) { | |
2164 int next_block = GetNextEmittedBlock(); | 2167 int next_block = GetNextEmittedBlock(); |
2165 right_block = chunk_->LookupDestination(right_block); | |
2166 left_block = chunk_->LookupDestination(left_block); | |
2167 | 2168 |
2168 if (right_block == left_block) { | 2169 if (right_block == left_block) { |
2169 EmitGoto(left_block); | 2170 EmitGoto(left_block); |
2170 } else if (left_block == next_block) { | 2171 } else if (left_block == next_block) { |
2171 __ b(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block)); | 2172 __ b(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block)); |
2172 } else if (right_block == next_block) { | 2173 } else if (right_block == next_block) { |
2173 __ b(cc, chunk_->GetAssemblyLabel(left_block)); | 2174 __ b(cc, chunk_->GetAssemblyLabel(left_block)); |
2174 } else { | 2175 } else { |
2175 __ b(cc, chunk_->GetAssemblyLabel(left_block)); | 2176 __ b(cc, chunk_->GetAssemblyLabel(left_block)); |
2176 __ b(chunk_->GetAssemblyLabel(right_block)); | 2177 __ b(chunk_->GetAssemblyLabel(right_block)); |
2177 } | 2178 } |
2178 } | 2179 } |
2179 | 2180 |
2180 | 2181 |
2181 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { | 2182 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { |
2182 __ stop("LBreak"); | 2183 __ stop("LBreak"); |
2183 } | 2184 } |
2184 | 2185 |
2185 | 2186 |
2186 void LCodeGen::DoBranch(LBranch* instr) { | 2187 void LCodeGen::DoBranch(LBranch* instr) { |
2187 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2188 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2189 | |
2190 Representation r = instr->hydrogen()->value()->representation(); | 2188 Representation r = instr->hydrogen()->value()->representation(); |
2191 if (r.IsInteger32() || r.IsSmi()) { | 2189 if (r.IsInteger32() || r.IsSmi()) { |
2192 ASSERT(!info()->IsStub()); | 2190 ASSERT(!info()->IsStub()); |
2193 Register reg = ToRegister(instr->value()); | 2191 Register reg = ToRegister(instr->value()); |
2194 __ cmp(reg, Operand::Zero()); | 2192 __ cmp(reg, Operand::Zero()); |
2195 EmitBranch(true_block, false_block, ne); | 2193 EmitBranch(instr, ne); |
2196 } else if (r.IsDouble()) { | 2194 } else if (r.IsDouble()) { |
2197 ASSERT(!info()->IsStub()); | 2195 ASSERT(!info()->IsStub()); |
2198 DwVfpRegister reg = ToDoubleRegister(instr->value()); | 2196 DwVfpRegister reg = ToDoubleRegister(instr->value()); |
2199 // Test the double value. Zero and NaN are false. | 2197 // Test the double value. Zero and NaN are false. |
2200 __ VFPCompareAndSetFlags(reg, 0.0); | 2198 __ VFPCompareAndSetFlags(reg, 0.0); |
2201 __ cmp(r0, r0, vs); // If NaN, set the Z flag. | 2199 __ cmp(r0, r0, vs); // If NaN, set the Z flag. |
2202 EmitBranch(true_block, false_block, ne); | 2200 EmitBranch(instr, ne); |
2203 } else { | 2201 } else { |
2204 ASSERT(r.IsTagged()); | 2202 ASSERT(r.IsTagged()); |
2205 Register reg = ToRegister(instr->value()); | 2203 Register reg = ToRegister(instr->value()); |
2206 HType type = instr->hydrogen()->value()->type(); | 2204 HType type = instr->hydrogen()->value()->type(); |
2207 if (type.IsBoolean()) { | 2205 if (type.IsBoolean()) { |
2208 ASSERT(!info()->IsStub()); | 2206 ASSERT(!info()->IsStub()); |
2209 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 2207 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
2210 EmitBranch(true_block, false_block, eq); | 2208 EmitBranch(instr, eq); |
2211 } else if (type.IsSmi()) { | 2209 } else if (type.IsSmi()) { |
2212 ASSERT(!info()->IsStub()); | 2210 ASSERT(!info()->IsStub()); |
2213 __ cmp(reg, Operand::Zero()); | 2211 __ cmp(reg, Operand::Zero()); |
2214 EmitBranch(true_block, false_block, ne); | 2212 EmitBranch(instr, ne); |
2215 } else { | 2213 } else { |
2216 Label* true_label = chunk_->GetAssemblyLabel(true_block); | |
2217 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
2218 | |
2219 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); | 2214 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); |
2220 // Avoid deopts in the case where we've never executed this path before. | 2215 // Avoid deopts in the case where we've never executed this path before. |
2221 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); | 2216 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); |
2222 | 2217 |
2223 if (expected.Contains(ToBooleanStub::UNDEFINED)) { | 2218 if (expected.Contains(ToBooleanStub::UNDEFINED)) { |
2224 // undefined -> false. | 2219 // undefined -> false. |
2225 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); | 2220 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); |
2226 __ b(eq, false_label); | 2221 __ b(eq, instr->FalseLabel(chunk_)); |
2227 } | 2222 } |
2228 if (expected.Contains(ToBooleanStub::BOOLEAN)) { | 2223 if (expected.Contains(ToBooleanStub::BOOLEAN)) { |
2229 // Boolean -> its value. | 2224 // Boolean -> its value. |
2230 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 2225 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
2231 __ b(eq, true_label); | 2226 __ b(eq, instr->TrueLabel(chunk_)); |
2232 __ CompareRoot(reg, Heap::kFalseValueRootIndex); | 2227 __ CompareRoot(reg, Heap::kFalseValueRootIndex); |
2233 __ b(eq, false_label); | 2228 __ b(eq, instr->FalseLabel(chunk_)); |
2234 } | 2229 } |
2235 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { | 2230 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { |
2236 // 'null' -> false. | 2231 // 'null' -> false. |
2237 __ CompareRoot(reg, Heap::kNullValueRootIndex); | 2232 __ CompareRoot(reg, Heap::kNullValueRootIndex); |
2238 __ b(eq, false_label); | 2233 __ b(eq, instr->FalseLabel(chunk_)); |
2239 } | 2234 } |
2240 | 2235 |
2241 if (expected.Contains(ToBooleanStub::SMI)) { | 2236 if (expected.Contains(ToBooleanStub::SMI)) { |
2242 // Smis: 0 -> false, all other -> true. | 2237 // Smis: 0 -> false, all other -> true. |
2243 __ cmp(reg, Operand::Zero()); | 2238 __ cmp(reg, Operand::Zero()); |
2244 __ b(eq, false_label); | 2239 __ b(eq, instr->FalseLabel(chunk_)); |
2245 __ JumpIfSmi(reg, true_label); | 2240 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
2246 } else if (expected.NeedsMap()) { | 2241 } else if (expected.NeedsMap()) { |
2247 // If we need a map later and have a Smi -> deopt. | 2242 // If we need a map later and have a Smi -> deopt. |
2248 __ SmiTst(reg); | 2243 __ SmiTst(reg); |
2249 DeoptimizeIf(eq, instr->environment()); | 2244 DeoptimizeIf(eq, instr->environment()); |
2250 } | 2245 } |
2251 | 2246 |
2252 const Register map = scratch0(); | 2247 const Register map = scratch0(); |
2253 if (expected.NeedsMap()) { | 2248 if (expected.NeedsMap()) { |
2254 __ ldr(map, FieldMemOperand(reg, HeapObject::kMapOffset)); | 2249 __ ldr(map, FieldMemOperand(reg, HeapObject::kMapOffset)); |
2255 | 2250 |
2256 if (expected.CanBeUndetectable()) { | 2251 if (expected.CanBeUndetectable()) { |
2257 // Undetectable -> false. | 2252 // Undetectable -> false. |
2258 __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset)); | 2253 __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset)); |
2259 __ tst(ip, Operand(1 << Map::kIsUndetectable)); | 2254 __ tst(ip, Operand(1 << Map::kIsUndetectable)); |
2260 __ b(ne, false_label); | 2255 __ b(ne, instr->FalseLabel(chunk_)); |
2261 } | 2256 } |
2262 } | 2257 } |
2263 | 2258 |
2264 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { | 2259 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { |
2265 // spec object -> true. | 2260 // spec object -> true. |
2266 __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE); | 2261 __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE); |
2267 __ b(ge, true_label); | 2262 __ b(ge, instr->TrueLabel(chunk_)); |
2268 } | 2263 } |
2269 | 2264 |
2270 if (expected.Contains(ToBooleanStub::STRING)) { | 2265 if (expected.Contains(ToBooleanStub::STRING)) { |
2271 // String value -> false iff empty. | 2266 // String value -> false iff empty. |
2272 Label not_string; | 2267 Label not_string; |
2273 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); | 2268 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); |
2274 __ b(ge, ¬_string); | 2269 __ b(ge, ¬_string); |
2275 __ ldr(ip, FieldMemOperand(reg, String::kLengthOffset)); | 2270 __ ldr(ip, FieldMemOperand(reg, String::kLengthOffset)); |
2276 __ cmp(ip, Operand::Zero()); | 2271 __ cmp(ip, Operand::Zero()); |
2277 __ b(ne, true_label); | 2272 __ b(ne, instr->TrueLabel(chunk_)); |
2278 __ b(false_label); | 2273 __ b(instr->FalseLabel(chunk_)); |
2279 __ bind(¬_string); | 2274 __ bind(¬_string); |
2280 } | 2275 } |
2281 | 2276 |
2282 if (expected.Contains(ToBooleanStub::SYMBOL)) { | 2277 if (expected.Contains(ToBooleanStub::SYMBOL)) { |
2283 // Symbol value -> true. | 2278 // Symbol value -> true. |
2284 __ CompareInstanceType(map, ip, SYMBOL_TYPE); | 2279 __ CompareInstanceType(map, ip, SYMBOL_TYPE); |
2285 __ b(eq, true_label); | 2280 __ b(eq, instr->TrueLabel(chunk_)); |
2286 } | 2281 } |
2287 | 2282 |
2288 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { | 2283 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { |
2289 // heap number -> false iff +0, -0, or NaN. | 2284 // heap number -> false iff +0, -0, or NaN. |
2290 DwVfpRegister dbl_scratch = double_scratch0(); | 2285 DwVfpRegister dbl_scratch = double_scratch0(); |
2291 Label not_heap_number; | 2286 Label not_heap_number; |
2292 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); | 2287 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); |
2293 __ b(ne, ¬_heap_number); | 2288 __ b(ne, ¬_heap_number); |
2294 __ vldr(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); | 2289 __ vldr(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); |
2295 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); | 2290 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); |
2296 __ cmp(r0, r0, vs); // NaN -> false. | 2291 __ cmp(r0, r0, vs); // NaN -> false. |
2297 __ b(eq, false_label); // +0, -0 -> false. | 2292 __ b(eq, instr->FalseLabel(chunk_)); // +0, -0 -> false. |
2298 __ b(true_label); | 2293 __ b(instr->TrueLabel(chunk_)); |
2299 __ bind(¬_heap_number); | 2294 __ bind(¬_heap_number); |
2300 } | 2295 } |
2301 | 2296 |
2302 // We've seen something for the first time -> deopt. | 2297 // We've seen something for the first time -> deopt. |
2303 DeoptimizeIf(al, instr->environment()); | 2298 DeoptimizeIf(al, instr->environment()); |
2304 } | 2299 } |
2305 } | 2300 } |
2306 } | 2301 } |
2307 | 2302 |
2308 | 2303 |
2309 void LCodeGen::EmitGoto(int block) { | 2304 void LCodeGen::EmitGoto(int block) { |
2310 if (!IsNextEmittedBlock(block)) { | 2305 if (!IsNextEmittedBlock(block)) { |
2311 __ jmp(chunk_->GetAssemblyLabel(chunk_->LookupDestination(block))); | 2306 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); |
2312 } | 2307 } |
2313 } | 2308 } |
2314 | 2309 |
2315 | 2310 |
2316 void LCodeGen::DoGoto(LGoto* instr) { | 2311 void LCodeGen::DoGoto(LGoto* instr) { |
2317 EmitGoto(instr->block_id()); | 2312 EmitGoto(instr->block_id()); |
2318 } | 2313 } |
2319 | 2314 |
2320 | 2315 |
2321 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { | 2316 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { |
(...skipping 20 matching lines...) Expand all Loading... |
2342 default: | 2337 default: |
2343 UNREACHABLE(); | 2338 UNREACHABLE(); |
2344 } | 2339 } |
2345 return cond; | 2340 return cond; |
2346 } | 2341 } |
2347 | 2342 |
2348 | 2343 |
2349 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 2344 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
2350 LOperand* left = instr->left(); | 2345 LOperand* left = instr->left(); |
2351 LOperand* right = instr->right(); | 2346 LOperand* right = instr->right(); |
2352 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2353 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2354 Condition cond = TokenToCondition(instr->op(), false); | 2347 Condition cond = TokenToCondition(instr->op(), false); |
2355 | 2348 |
2356 if (left->IsConstantOperand() && right->IsConstantOperand()) { | 2349 if (left->IsConstantOperand() && right->IsConstantOperand()) { |
2357 // We can statically evaluate the comparison. | 2350 // We can statically evaluate the comparison. |
2358 double left_val = ToDouble(LConstantOperand::cast(left)); | 2351 double left_val = ToDouble(LConstantOperand::cast(left)); |
2359 double right_val = ToDouble(LConstantOperand::cast(right)); | 2352 double right_val = ToDouble(LConstantOperand::cast(right)); |
2360 int next_block = | 2353 int next_block = EvalComparison(instr->op(), left_val, right_val) ? |
2361 EvalComparison(instr->op(), left_val, right_val) ? true_block | 2354 instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_); |
2362 : false_block; | |
2363 EmitGoto(next_block); | 2355 EmitGoto(next_block); |
2364 } else { | 2356 } else { |
2365 if (instr->is_double()) { | 2357 if (instr->is_double()) { |
2366 // Compare left and right operands as doubles and load the | 2358 // Compare left and right operands as doubles and load the |
2367 // resulting flags into the normal status register. | 2359 // resulting flags into the normal status register. |
2368 __ VFPCompareAndSetFlags(ToDoubleRegister(left), ToDoubleRegister(right)); | 2360 __ VFPCompareAndSetFlags(ToDoubleRegister(left), ToDoubleRegister(right)); |
2369 // If a NaN is involved, i.e. the result is unordered (V set), | 2361 // If a NaN is involved, i.e. the result is unordered (V set), |
2370 // jump to false block label. | 2362 // jump to false block label. |
2371 __ b(vs, chunk_->GetAssemblyLabel(false_block)); | 2363 __ b(vs, instr->FalseLabel(chunk_)); |
2372 } else { | 2364 } else { |
2373 if (right->IsConstantOperand()) { | 2365 if (right->IsConstantOperand()) { |
2374 int32_t value = ToInteger32(LConstantOperand::cast(right)); | 2366 int32_t value = ToInteger32(LConstantOperand::cast(right)); |
2375 if (instr->hydrogen_value()->representation().IsSmi()) { | 2367 if (instr->hydrogen_value()->representation().IsSmi()) { |
2376 __ cmp(ToRegister(left), Operand(Smi::FromInt(value))); | 2368 __ cmp(ToRegister(left), Operand(Smi::FromInt(value))); |
2377 } else { | 2369 } else { |
2378 __ cmp(ToRegister(left), Operand(value)); | 2370 __ cmp(ToRegister(left), Operand(value)); |
2379 } | 2371 } |
2380 } else if (left->IsConstantOperand()) { | 2372 } else if (left->IsConstantOperand()) { |
2381 int32_t value = ToInteger32(LConstantOperand::cast(left)); | 2373 int32_t value = ToInteger32(LConstantOperand::cast(left)); |
2382 if (instr->hydrogen_value()->representation().IsSmi()) { | 2374 if (instr->hydrogen_value()->representation().IsSmi()) { |
2383 __ cmp(ToRegister(right), Operand(Smi::FromInt(value))); | 2375 __ cmp(ToRegister(right), Operand(Smi::FromInt(value))); |
2384 } else { | 2376 } else { |
2385 __ cmp(ToRegister(right), Operand(value)); | 2377 __ cmp(ToRegister(right), Operand(value)); |
2386 } | 2378 } |
2387 // We transposed the operands. Reverse the condition. | 2379 // We transposed the operands. Reverse the condition. |
2388 cond = ReverseCondition(cond); | 2380 cond = ReverseCondition(cond); |
2389 } else { | 2381 } else { |
2390 __ cmp(ToRegister(left), ToRegister(right)); | 2382 __ cmp(ToRegister(left), ToRegister(right)); |
2391 } | 2383 } |
2392 } | 2384 } |
2393 EmitBranch(true_block, false_block, cond); | 2385 EmitBranch(instr, cond); |
2394 } | 2386 } |
2395 } | 2387 } |
2396 | 2388 |
2397 | 2389 |
2398 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { | 2390 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { |
2399 Register left = ToRegister(instr->left()); | 2391 Register left = ToRegister(instr->left()); |
2400 Register right = ToRegister(instr->right()); | 2392 Register right = ToRegister(instr->right()); |
2401 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2402 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2403 | 2393 |
2404 __ cmp(left, Operand(right)); | 2394 __ cmp(left, Operand(right)); |
2405 EmitBranch(true_block, false_block, eq); | 2395 EmitBranch(instr, eq); |
2406 } | 2396 } |
2407 | 2397 |
2408 | 2398 |
2409 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { | 2399 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { |
2410 Register left = ToRegister(instr->left()); | 2400 Register left = ToRegister(instr->left()); |
2411 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2412 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2413 | 2401 |
2414 __ cmp(left, Operand(instr->hydrogen()->right())); | 2402 __ cmp(left, Operand(instr->hydrogen()->right())); |
2415 EmitBranch(true_block, false_block, eq); | 2403 EmitBranch(instr, eq); |
2416 } | 2404 } |
2417 | 2405 |
2418 | 2406 |
2419 Condition LCodeGen::EmitIsObject(Register input, | 2407 Condition LCodeGen::EmitIsObject(Register input, |
2420 Register temp1, | 2408 Register temp1, |
2421 Label* is_not_object, | 2409 Label* is_not_object, |
2422 Label* is_object) { | 2410 Label* is_object) { |
2423 Register temp2 = scratch0(); | 2411 Register temp2 = scratch0(); |
2424 __ JumpIfSmi(input, is_not_object); | 2412 __ JumpIfSmi(input, is_not_object); |
2425 | 2413 |
(...skipping 14 matching lines...) Expand all Loading... |
2440 __ b(lt, is_not_object); | 2428 __ b(lt, is_not_object); |
2441 __ cmp(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 2429 __ cmp(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
2442 return le; | 2430 return le; |
2443 } | 2431 } |
2444 | 2432 |
2445 | 2433 |
2446 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 2434 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
2447 Register reg = ToRegister(instr->value()); | 2435 Register reg = ToRegister(instr->value()); |
2448 Register temp1 = ToRegister(instr->temp()); | 2436 Register temp1 = ToRegister(instr->temp()); |
2449 | 2437 |
2450 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2438 Condition true_cond = |
2451 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2439 EmitIsObject(reg, temp1, |
2452 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 2440 instr->FalseLabel(chunk_), instr->TrueLabel(chunk_)); |
2453 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
2454 | 2441 |
2455 Condition true_cond = | 2442 EmitBranch(instr, true_cond); |
2456 EmitIsObject(reg, temp1, false_label, true_label); | |
2457 | |
2458 EmitBranch(true_block, false_block, true_cond); | |
2459 } | 2443 } |
2460 | 2444 |
2461 | 2445 |
2462 Condition LCodeGen::EmitIsString(Register input, | 2446 Condition LCodeGen::EmitIsString(Register input, |
2463 Register temp1, | 2447 Register temp1, |
2464 Label* is_not_string) { | 2448 Label* is_not_string) { |
2465 __ JumpIfSmi(input, is_not_string); | 2449 __ JumpIfSmi(input, is_not_string); |
2466 __ CompareObjectType(input, temp1, temp1, FIRST_NONSTRING_TYPE); | 2450 __ CompareObjectType(input, temp1, temp1, FIRST_NONSTRING_TYPE); |
2467 | 2451 |
2468 return lt; | 2452 return lt; |
2469 } | 2453 } |
2470 | 2454 |
2471 | 2455 |
2472 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { | 2456 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { |
2473 Register reg = ToRegister(instr->value()); | 2457 Register reg = ToRegister(instr->value()); |
2474 Register temp1 = ToRegister(instr->temp()); | 2458 Register temp1 = ToRegister(instr->temp()); |
2475 | 2459 |
2476 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2460 Condition true_cond = |
2477 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2461 EmitIsString(reg, temp1, instr->FalseLabel(chunk_)); |
2478 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
2479 | 2462 |
2480 Condition true_cond = | 2463 EmitBranch(instr, true_cond); |
2481 EmitIsString(reg, temp1, false_label); | |
2482 | |
2483 EmitBranch(true_block, false_block, true_cond); | |
2484 } | 2464 } |
2485 | 2465 |
2486 | 2466 |
2487 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 2467 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
2488 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2489 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2490 | |
2491 Register input_reg = EmitLoadRegister(instr->value(), ip); | 2468 Register input_reg = EmitLoadRegister(instr->value(), ip); |
2492 __ SmiTst(input_reg); | 2469 __ SmiTst(input_reg); |
2493 EmitBranch(true_block, false_block, eq); | 2470 EmitBranch(instr, eq); |
2494 } | 2471 } |
2495 | 2472 |
2496 | 2473 |
2497 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { | 2474 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { |
2498 Register input = ToRegister(instr->value()); | 2475 Register input = ToRegister(instr->value()); |
2499 Register temp = ToRegister(instr->temp()); | 2476 Register temp = ToRegister(instr->temp()); |
2500 | 2477 |
2501 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2478 __ JumpIfSmi(input, instr->FalseLabel(chunk_)); |
2502 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2503 | |
2504 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); | |
2505 __ ldr(temp, FieldMemOperand(input, HeapObject::kMapOffset)); | 2479 __ ldr(temp, FieldMemOperand(input, HeapObject::kMapOffset)); |
2506 __ ldrb(temp, FieldMemOperand(temp, Map::kBitFieldOffset)); | 2480 __ ldrb(temp, FieldMemOperand(temp, Map::kBitFieldOffset)); |
2507 __ tst(temp, Operand(1 << Map::kIsUndetectable)); | 2481 __ tst(temp, Operand(1 << Map::kIsUndetectable)); |
2508 EmitBranch(true_block, false_block, ne); | 2482 EmitBranch(instr, ne); |
2509 } | 2483 } |
2510 | 2484 |
2511 | 2485 |
2512 static Condition ComputeCompareCondition(Token::Value op) { | 2486 static Condition ComputeCompareCondition(Token::Value op) { |
2513 switch (op) { | 2487 switch (op) { |
2514 case Token::EQ_STRICT: | 2488 case Token::EQ_STRICT: |
2515 case Token::EQ: | 2489 case Token::EQ: |
2516 return eq; | 2490 return eq; |
2517 case Token::LT: | 2491 case Token::LT: |
2518 return lt; | 2492 return lt; |
2519 case Token::GT: | 2493 case Token::GT: |
2520 return gt; | 2494 return gt; |
2521 case Token::LTE: | 2495 case Token::LTE: |
2522 return le; | 2496 return le; |
2523 case Token::GTE: | 2497 case Token::GTE: |
2524 return ge; | 2498 return ge; |
2525 default: | 2499 default: |
2526 UNREACHABLE(); | 2500 UNREACHABLE(); |
2527 return kNoCondition; | 2501 return kNoCondition; |
2528 } | 2502 } |
2529 } | 2503 } |
2530 | 2504 |
2531 | 2505 |
2532 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { | 2506 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { |
2533 Token::Value op = instr->op(); | 2507 Token::Value op = instr->op(); |
2534 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2535 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2536 | 2508 |
2537 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 2509 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
2538 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2510 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2539 // This instruction also signals no smi code inlined. | 2511 // This instruction also signals no smi code inlined. |
2540 __ cmp(r0, Operand::Zero()); | 2512 __ cmp(r0, Operand::Zero()); |
2541 | 2513 |
2542 Condition condition = ComputeCompareCondition(op); | 2514 Condition condition = ComputeCompareCondition(op); |
2543 | 2515 |
2544 EmitBranch(true_block, false_block, condition); | 2516 EmitBranch(instr, condition); |
2545 } | 2517 } |
2546 | 2518 |
2547 | 2519 |
2548 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { | 2520 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { |
2549 InstanceType from = instr->from(); | 2521 InstanceType from = instr->from(); |
2550 InstanceType to = instr->to(); | 2522 InstanceType to = instr->to(); |
2551 if (from == FIRST_TYPE) return to; | 2523 if (from == FIRST_TYPE) return to; |
2552 ASSERT(from == to || to == LAST_TYPE); | 2524 ASSERT(from == to || to == LAST_TYPE); |
2553 return from; | 2525 return from; |
2554 } | 2526 } |
2555 | 2527 |
2556 | 2528 |
2557 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { | 2529 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { |
2558 InstanceType from = instr->from(); | 2530 InstanceType from = instr->from(); |
2559 InstanceType to = instr->to(); | 2531 InstanceType to = instr->to(); |
2560 if (from == to) return eq; | 2532 if (from == to) return eq; |
2561 if (to == LAST_TYPE) return hs; | 2533 if (to == LAST_TYPE) return hs; |
2562 if (from == FIRST_TYPE) return ls; | 2534 if (from == FIRST_TYPE) return ls; |
2563 UNREACHABLE(); | 2535 UNREACHABLE(); |
2564 return eq; | 2536 return eq; |
2565 } | 2537 } |
2566 | 2538 |
2567 | 2539 |
2568 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 2540 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
2569 Register scratch = scratch0(); | 2541 Register scratch = scratch0(); |
2570 Register input = ToRegister(instr->value()); | 2542 Register input = ToRegister(instr->value()); |
2571 | 2543 |
2572 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2544 __ JumpIfSmi(input, instr->FalseLabel(chunk_)); |
2573 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2574 | |
2575 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
2576 | |
2577 __ JumpIfSmi(input, false_label); | |
2578 | 2545 |
2579 __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen())); | 2546 __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen())); |
2580 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); | 2547 EmitBranch(instr, BranchCondition(instr->hydrogen())); |
2581 } | 2548 } |
2582 | 2549 |
2583 | 2550 |
2584 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { | 2551 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { |
2585 Register input = ToRegister(instr->value()); | 2552 Register input = ToRegister(instr->value()); |
2586 Register result = ToRegister(instr->result()); | 2553 Register result = ToRegister(instr->result()); |
2587 | 2554 |
2588 __ AssertString(input); | 2555 __ AssertString(input); |
2589 | 2556 |
2590 __ ldr(result, FieldMemOperand(input, String::kHashFieldOffset)); | 2557 __ ldr(result, FieldMemOperand(input, String::kHashFieldOffset)); |
2591 __ IndexFromHash(result, result); | 2558 __ IndexFromHash(result, result); |
2592 } | 2559 } |
2593 | 2560 |
2594 | 2561 |
2595 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 2562 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
2596 LHasCachedArrayIndexAndBranch* instr) { | 2563 LHasCachedArrayIndexAndBranch* instr) { |
2597 Register input = ToRegister(instr->value()); | 2564 Register input = ToRegister(instr->value()); |
2598 Register scratch = scratch0(); | 2565 Register scratch = scratch0(); |
2599 | 2566 |
2600 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2601 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2602 | |
2603 __ ldr(scratch, | 2567 __ ldr(scratch, |
2604 FieldMemOperand(input, String::kHashFieldOffset)); | 2568 FieldMemOperand(input, String::kHashFieldOffset)); |
2605 __ tst(scratch, Operand(String::kContainsCachedArrayIndexMask)); | 2569 __ tst(scratch, Operand(String::kContainsCachedArrayIndexMask)); |
2606 EmitBranch(true_block, false_block, eq); | 2570 EmitBranch(instr, eq); |
2607 } | 2571 } |
2608 | 2572 |
2609 | 2573 |
2610 // Branches to a label or falls through with the answer in flags. Trashes | 2574 // Branches to a label or falls through with the answer in flags. Trashes |
2611 // the temp registers, but not the input. | 2575 // the temp registers, but not the input. |
2612 void LCodeGen::EmitClassOfTest(Label* is_true, | 2576 void LCodeGen::EmitClassOfTest(Label* is_true, |
2613 Label* is_false, | 2577 Label* is_false, |
2614 Handle<String>class_name, | 2578 Handle<String>class_name, |
2615 Register input, | 2579 Register input, |
2616 Register temp, | 2580 Register temp, |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2673 // End with the answer in flags. | 2637 // End with the answer in flags. |
2674 } | 2638 } |
2675 | 2639 |
2676 | 2640 |
2677 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 2641 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
2678 Register input = ToRegister(instr->value()); | 2642 Register input = ToRegister(instr->value()); |
2679 Register temp = scratch0(); | 2643 Register temp = scratch0(); |
2680 Register temp2 = ToRegister(instr->temp()); | 2644 Register temp2 = ToRegister(instr->temp()); |
2681 Handle<String> class_name = instr->hydrogen()->class_name(); | 2645 Handle<String> class_name = instr->hydrogen()->class_name(); |
2682 | 2646 |
2683 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2647 EmitClassOfTest(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), |
2684 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2648 class_name, input, temp, temp2); |
2685 | 2649 |
2686 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 2650 EmitBranch(instr, eq); |
2687 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
2688 | |
2689 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); | |
2690 | |
2691 EmitBranch(true_block, false_block, eq); | |
2692 } | 2651 } |
2693 | 2652 |
2694 | 2653 |
2695 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 2654 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
2696 Register reg = ToRegister(instr->value()); | 2655 Register reg = ToRegister(instr->value()); |
2697 Register temp = ToRegister(instr->temp()); | 2656 Register temp = ToRegister(instr->temp()); |
2698 int true_block = instr->true_block_id(); | |
2699 int false_block = instr->false_block_id(); | |
2700 | 2657 |
2701 __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); | 2658 __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); |
2702 __ cmp(temp, Operand(instr->map())); | 2659 __ cmp(temp, Operand(instr->map())); |
2703 EmitBranch(true_block, false_block, eq); | 2660 EmitBranch(instr, eq); |
2704 } | 2661 } |
2705 | 2662 |
2706 | 2663 |
2707 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 2664 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
2708 ASSERT(ToRegister(instr->left()).is(r0)); // Object is in r0. | 2665 ASSERT(ToRegister(instr->left()).is(r0)); // Object is in r0. |
2709 ASSERT(ToRegister(instr->right()).is(r1)); // Function is in r1. | 2666 ASSERT(ToRegister(instr->right()).is(r1)); // Function is in r1. |
2710 | 2667 |
2711 InstanceofStub stub(InstanceofStub::kArgsInRegisters); | 2668 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
2712 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 2669 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
2713 | 2670 |
(...skipping 2876 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5590 | 5547 |
5591 void LCodeGen::DoTypeof(LTypeof* instr) { | 5548 void LCodeGen::DoTypeof(LTypeof* instr) { |
5592 Register input = ToRegister(instr->value()); | 5549 Register input = ToRegister(instr->value()); |
5593 __ push(input); | 5550 __ push(input); |
5594 CallRuntime(Runtime::kTypeof, 1, instr); | 5551 CallRuntime(Runtime::kTypeof, 1, instr); |
5595 } | 5552 } |
5596 | 5553 |
5597 | 5554 |
5598 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 5555 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
5599 Register input = ToRegister(instr->value()); | 5556 Register input = ToRegister(instr->value()); |
5600 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
5601 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
5602 Label* true_label = chunk_->GetAssemblyLabel(true_block); | |
5603 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
5604 | 5557 |
5605 Condition final_branch_condition = EmitTypeofIs(true_label, | 5558 Condition final_branch_condition = EmitTypeofIs(instr->TrueLabel(chunk_), |
5606 false_label, | 5559 instr->FalseLabel(chunk_), |
5607 input, | 5560 input, |
5608 instr->type_literal()); | 5561 instr->type_literal()); |
5609 if (final_branch_condition != kNoCondition) { | 5562 if (final_branch_condition != kNoCondition) { |
5610 EmitBranch(true_block, false_block, final_branch_condition); | 5563 EmitBranch(instr, final_branch_condition); |
5611 } | 5564 } |
5612 } | 5565 } |
5613 | 5566 |
5614 | 5567 |
5615 Condition LCodeGen::EmitTypeofIs(Label* true_label, | 5568 Condition LCodeGen::EmitTypeofIs(Label* true_label, |
5616 Label* false_label, | 5569 Label* false_label, |
5617 Register input, | 5570 Register input, |
5618 Handle<String> type_name) { | 5571 Handle<String> type_name) { |
5619 Condition final_branch_condition = kNoCondition; | 5572 Condition final_branch_condition = kNoCondition; |
5620 Register scratch = scratch0(); | 5573 Register scratch = scratch0(); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5685 } else { | 5638 } else { |
5686 __ b(false_label); | 5639 __ b(false_label); |
5687 } | 5640 } |
5688 | 5641 |
5689 return final_branch_condition; | 5642 return final_branch_condition; |
5690 } | 5643 } |
5691 | 5644 |
5692 | 5645 |
5693 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 5646 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
5694 Register temp1 = ToRegister(instr->temp()); | 5647 Register temp1 = ToRegister(instr->temp()); |
5695 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
5696 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
5697 | 5648 |
5698 EmitIsConstructCall(temp1, scratch0()); | 5649 EmitIsConstructCall(temp1, scratch0()); |
5699 EmitBranch(true_block, false_block, eq); | 5650 EmitBranch(instr, eq); |
5700 } | 5651 } |
5701 | 5652 |
5702 | 5653 |
5703 void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) { | 5654 void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) { |
5704 ASSERT(!temp1.is(temp2)); | 5655 ASSERT(!temp1.is(temp2)); |
5705 // Get the frame pointer for the calling frame. | 5656 // Get the frame pointer for the calling frame. |
5706 __ ldr(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 5657 __ ldr(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
5707 | 5658 |
5708 // Skip the arguments adaptor frame if it exists. | 5659 // Skip the arguments adaptor frame if it exists. |
5709 Label check_frame_marker; | 5660 Label check_frame_marker; |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5954 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 5905 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); |
5955 __ ldr(result, FieldMemOperand(scratch, | 5906 __ ldr(result, FieldMemOperand(scratch, |
5956 FixedArray::kHeaderSize - kPointerSize)); | 5907 FixedArray::kHeaderSize - kPointerSize)); |
5957 __ bind(&done); | 5908 __ bind(&done); |
5958 } | 5909 } |
5959 | 5910 |
5960 | 5911 |
5961 #undef __ | 5912 #undef __ |
5962 | 5913 |
5963 } } // namespace v8::internal | 5914 } } // namespace v8::internal |
OLD | NEW |