Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 201 } | 201 } |
| 202 } | 202 } |
| 203 | 203 |
| 204 | 204 |
| 205 LocationSummary* AssertAssignableInstr::MakeLocationSummary() const { | 205 LocationSummary* AssertAssignableInstr::MakeLocationSummary() const { |
| 206 const intptr_t kNumInputs = 3; | 206 const intptr_t kNumInputs = 3; |
| 207 const intptr_t kNumTemps = 0; | 207 const intptr_t kNumTemps = 0; |
| 208 LocationSummary* summary = | 208 LocationSummary* summary = |
| 209 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 209 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 210 summary->set_in(0, Location::RegisterLocation(R0)); // Value. | 210 summary->set_in(0, Location::RegisterLocation(R0)); // Value. |
| 211 summary->set_in(1, Location::RegisterLocation(R1)); // Instantiator. | 211 summary->set_in(1, Location::RegisterLocation(R2)); // Instantiator. |
| 212 summary->set_in(2, Location::RegisterLocation(R2)); // Type arguments. | 212 summary->set_in(2, Location::RegisterLocation(R1)); // Type arguments. |
| 213 summary->set_out(Location::RegisterLocation(R0)); | 213 summary->set_out(Location::RegisterLocation(R0)); |
| 214 return summary; | 214 return summary; |
| 215 } | 215 } |
| 216 | 216 |
| 217 | 217 |
| 218 LocationSummary* AssertBooleanInstr::MakeLocationSummary() const { | 218 LocationSummary* AssertBooleanInstr::MakeLocationSummary() const { |
| 219 const intptr_t kNumInputs = 1; | 219 const intptr_t kNumInputs = 1; |
| 220 const intptr_t kNumTemps = 0; | 220 const intptr_t kNumTemps = 0; |
| 221 LocationSummary* locs = | 221 LocationSummary* locs = |
| 222 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 222 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 337 LocationSummary* locs = | 337 LocationSummary* locs = |
| 338 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 338 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 339 UNIMPLEMENTED(); // TODO(regis): Verify register allocation. | 339 UNIMPLEMENTED(); // TODO(regis): Verify register allocation. |
| 340 return locs; | 340 return locs; |
| 341 } | 341 } |
| 342 const intptr_t kNumTemps = 1; | 342 const intptr_t kNumTemps = 1; |
| 343 LocationSummary* locs = | 343 LocationSummary* locs = |
| 344 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 344 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 345 locs->set_in(0, Location::RegisterLocation(R1)); | 345 locs->set_in(0, Location::RegisterLocation(R1)); |
| 346 locs->set_in(1, Location::RegisterLocation(R0)); | 346 locs->set_in(1, Location::RegisterLocation(R0)); |
| 347 locs->set_temp(0, Location::RegisterLocation(R6)); | 347 locs->set_temp(0, Location::RegisterLocation(R5)); |
| 348 locs->set_out(Location::RegisterLocation(R0)); | 348 locs->set_out(Location::RegisterLocation(R0)); |
| 349 return locs; | 349 return locs; |
| 350 } | 350 } |
| 351 | 351 |
| 352 | 352 |
| 353 // R1: left. | 353 // R1: left. |
| 354 // R0: right. | 354 // R0: right. |
| 355 // Uses R6 to load ic_call_data. | 355 // Uses R5 to load ic_call_data. |
| 356 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, | 356 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, |
| 357 intptr_t deopt_id, | 357 intptr_t deopt_id, |
| 358 intptr_t token_pos, | 358 intptr_t token_pos, |
| 359 Token::Kind kind, | 359 Token::Kind kind, |
| 360 LocationSummary* locs, | 360 LocationSummary* locs, |
| 361 const ICData& original_ic_data) { | 361 const ICData& original_ic_data) { |
| 362 if (!compiler->is_optimizing()) { | 362 if (!compiler->is_optimizing()) { |
| 363 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 363 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 364 deopt_id, | 364 deopt_id, |
| 365 token_pos); | 365 token_pos); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 398 kNoArgumentNames, | 398 kNoArgumentNames, |
| 399 locs, | 399 locs, |
| 400 equality_ic_data); | 400 equality_ic_data); |
| 401 Label check_ne; | 401 Label check_ne; |
| 402 __ b(&check_ne); | 402 __ b(&check_ne); |
| 403 | 403 |
| 404 __ Bind(&check_identity); | 404 __ Bind(&check_identity); |
| 405 Label equality_done; | 405 Label equality_done; |
| 406 if (compiler->is_optimizing()) { | 406 if (compiler->is_optimizing()) { |
| 407 // No need to update IC data. | 407 // No need to update IC data. |
| 408 Label is_true; | |
| 409 __ cmp(R0, ShifterOperand(R1)); | 408 __ cmp(R0, ShifterOperand(R1)); |
| 410 __ b(&is_true, EQ); | 409 __ LoadObject(R0, (kind == Token::kEQ) ? Bool::False() : Bool::True(), NE); |
| 411 __ LoadObject(R0, (kind == Token::kEQ) ? Bool::False() : Bool::True()); | 410 __ LoadObject(R0, (kind == Token::kEQ) ? Bool::True() : Bool::False(), EQ); |
| 412 __ b(&equality_done); | |
| 413 __ Bind(&is_true); | |
| 414 __ LoadObject(R0, (kind == Token::kEQ) ? Bool::True() : Bool::False()); | |
| 415 if (kind == Token::kNE) { | 411 if (kind == Token::kNE) { |
| 416 // Skip not-equal result conversion. | 412 // Skip not-equal result conversion. |
| 417 __ b(&equality_done); | 413 __ b(&equality_done); |
| 418 } | 414 } |
| 419 } else { | 415 } else { |
| 420 // Call stub, load IC data in register. The stub will update ICData if | 416 // Call stub, load IC data in register. The stub will update ICData if |
| 421 // necessary. | 417 // necessary. |
| 422 Register ic_data_reg = locs->temp(0).reg(); | 418 Register ic_data_reg = locs->temp(0).reg(); |
| 423 ASSERT(ic_data_reg == R6); // Stub depends on it. | 419 ASSERT(ic_data_reg == R5); // Stub depends on it. |
| 424 __ LoadObject(ic_data_reg, equality_ic_data); | 420 __ LoadObject(ic_data_reg, equality_ic_data); |
| 425 // Pass left in R1 and right in R0. | 421 // Pass left in R1 and right in R0. |
| 426 compiler->GenerateCall(token_pos, | 422 compiler->GenerateCall(token_pos, |
| 427 &StubCode::EqualityWithNullArgLabel(), | 423 &StubCode::EqualityWithNullArgLabel(), |
| 428 PcDescriptors::kOther, | 424 PcDescriptors::kOther, |
| 429 locs); | 425 locs); |
| 430 } | 426 } |
| 431 __ Bind(&check_ne); | 427 __ Bind(&check_ne); |
| 432 if (kind == Token::kNE) { | 428 if (kind == Token::kNE) { |
| 433 Label true_label, done; | |
| 434 // Negate the condition: true label returns false and vice versa. | 429 // Negate the condition: true label returns false and vice versa. |
| 435 __ CompareObject(R0, Bool::True()); | 430 __ CompareObject(R0, Bool::True()); |
| 436 __ b(&true_label, EQ); | 431 __ LoadObject(R0, Bool::True(), NE); |
| 437 __ LoadObject(R0, Bool::True()); | 432 __ LoadObject(R0, Bool::False(), EQ); |
| 438 __ b(&done); | |
| 439 __ Bind(&true_label); | |
| 440 __ LoadObject(R0, Bool::False()); | |
| 441 __ Bind(&done); | |
| 442 } | 433 } |
| 443 __ Bind(&equality_done); | 434 __ Bind(&equality_done); |
| 444 } | 435 } |
| 445 | 436 |
| 446 | 437 |
| 447 static void LoadValueCid(FlowGraphCompiler* compiler, | 438 static void LoadValueCid(FlowGraphCompiler* compiler, |
| 448 Register value_cid_reg, | 439 Register value_cid_reg, |
| 449 Register value_reg, | 440 Register value_reg, |
| 450 Label* value_is_smi = NULL) { | 441 Label* value_is_smi = NULL) { |
| 451 Label done; | 442 Label done; |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 481 LocationSummary* locs, | 472 LocationSummary* locs, |
| 482 Token::Kind kind, | 473 Token::Kind kind, |
| 483 BranchInstr* branch, | 474 BranchInstr* branch, |
| 484 const ICData& ic_data, | 475 const ICData& ic_data, |
| 485 intptr_t deopt_id, | 476 intptr_t deopt_id, |
| 486 intptr_t token_pos) { | 477 intptr_t token_pos) { |
| 487 UNIMPLEMENTED(); | 478 UNIMPLEMENTED(); |
| 488 } | 479 } |
| 489 | 480 |
| 490 | 481 |
| 482 static Condition NegateCondition(Condition condition) { | |
| 483 switch (condition) { | |
| 484 case EQ: return NE; | |
| 485 case NE: return EQ; | |
| 486 case LT: return GE; | |
| 487 case LE: return GT; | |
| 488 case GT: return LE; | |
| 489 case GE: return LT; | |
| 490 case CC: return CS; | |
| 491 case LS: return HI; | |
| 492 case HI: return LS; | |
| 493 case CS: return CC; | |
| 494 default: | |
| 495 OS::Print("Error %d\n", condition); | |
|
srdjan
2013/04/19 22:56:40
You could use PrintErr
regis
2013/04/19 23:19:19
I deleted this line here and in the Intel sources.
| |
| 496 UNIMPLEMENTED(); | |
| 497 return EQ; | |
| 498 } | |
| 499 } | |
| 500 | |
| 501 | |
| 491 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 502 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 492 const LocationSummary& locs, | 503 const LocationSummary& locs, |
| 493 Token::Kind kind, | 504 Token::Kind kind, |
| 494 BranchInstr* branch) { | 505 BranchInstr* branch) { |
| 495 Location left = locs.in(0); | 506 Location left = locs.in(0); |
| 496 Location right = locs.in(1); | 507 Location right = locs.in(1); |
| 497 ASSERT(!left.IsConstant() || !right.IsConstant()); | 508 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 498 | 509 |
| 499 Condition true_condition = TokenKindToSmiCondition(kind); | 510 Condition true_condition = TokenKindToSmiCondition(kind); |
| 500 | 511 |
| 501 if (left.IsConstant()) { | 512 if (left.IsConstant()) { |
| 502 __ CompareObject(right.reg(), left.constant()); | 513 __ CompareObject(right.reg(), left.constant()); |
| 503 true_condition = FlowGraphCompiler::FlipCondition(true_condition); | 514 true_condition = FlowGraphCompiler::FlipCondition(true_condition); |
| 504 } else if (right.IsConstant()) { | 515 } else if (right.IsConstant()) { |
| 505 __ CompareObject(left.reg(), right.constant()); | 516 __ CompareObject(left.reg(), right.constant()); |
| 506 } else { | 517 } else { |
| 507 __ cmp(left.reg(), ShifterOperand(right.reg())); | 518 __ cmp(left.reg(), ShifterOperand(right.reg())); |
| 508 } | 519 } |
| 509 | 520 |
| 510 if (branch != NULL) { | 521 if (branch != NULL) { |
| 511 branch->EmitBranchOnCondition(compiler, true_condition); | 522 branch->EmitBranchOnCondition(compiler, true_condition); |
| 512 } else { | 523 } else { |
| 513 Register result = locs.out().reg(); | 524 Register result = locs.out().reg(); |
| 514 Label done, is_true; | 525 __ LoadObject(result, Bool::True(), true_condition); |
| 515 __ b(&is_true, true_condition); | 526 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
| 516 __ LoadObject(result, Bool::False()); | |
| 517 __ b(&done); | |
| 518 __ Bind(&is_true); | |
| 519 __ LoadObject(result, Bool::True()); | |
| 520 __ Bind(&done); | |
| 521 } | 527 } |
| 522 } | 528 } |
| 523 | 529 |
| 524 | 530 |
| 525 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, | 531 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, |
| 526 const LocationSummary& locs, | 532 const LocationSummary& locs, |
| 527 Token::Kind kind, | 533 Token::Kind kind, |
| 528 BranchInstr* branch) { | 534 BranchInstr* branch) { |
| 529 UNIMPLEMENTED(); | 535 UNIMPLEMENTED(); |
| 530 } | 536 } |
| (...skipping 1582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2113 } | 2119 } |
| 2114 | 2120 |
| 2115 // We can fall through if the successor is the next block in the list. | 2121 // We can fall through if the successor is the next block in the list. |
| 2116 // Otherwise, we need a jump. | 2122 // Otherwise, we need a jump. |
| 2117 if (!compiler->CanFallThroughTo(successor())) { | 2123 if (!compiler->CanFallThroughTo(successor())) { |
| 2118 __ b(compiler->GetJumpLabel(successor())); | 2124 __ b(compiler->GetJumpLabel(successor())); |
| 2119 } | 2125 } |
| 2120 } | 2126 } |
| 2121 | 2127 |
| 2122 | 2128 |
| 2123 static Condition NegateCondition(Condition condition) { | |
| 2124 switch (condition) { | |
| 2125 case EQ: return NE; | |
| 2126 case NE: return EQ; | |
| 2127 case LT: return GE; | |
| 2128 case LE: return GT; | |
| 2129 case GT: return LE; | |
| 2130 case GE: return LT; | |
| 2131 case CC: return CS; | |
| 2132 case LS: return HI; | |
| 2133 case HI: return LS; | |
| 2134 case CS: return CC; | |
| 2135 default: | |
| 2136 OS::Print("Error %d\n", condition); | |
| 2137 UNIMPLEMENTED(); | |
| 2138 return EQ; | |
| 2139 } | |
| 2140 } | |
| 2141 | |
| 2142 | |
| 2143 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, | 2129 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, |
| 2144 bool value) { | 2130 bool value) { |
| 2145 if (value && !compiler->CanFallThroughTo(true_successor())) { | 2131 if (value && !compiler->CanFallThroughTo(true_successor())) { |
| 2146 __ b(compiler->GetJumpLabel(true_successor())); | 2132 __ b(compiler->GetJumpLabel(true_successor())); |
| 2147 } else if (!value && !compiler->CanFallThroughTo(false_successor())) { | 2133 } else if (!value && !compiler->CanFallThroughTo(false_successor())) { |
| 2148 __ b(compiler->GetJumpLabel(false_successor())); | 2134 __ b(compiler->GetJumpLabel(false_successor())); |
| 2149 } | 2135 } |
| 2150 } | 2136 } |
| 2151 | 2137 |
| 2152 | 2138 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2214 compiler->EmitEqualityRegConstCompare(left.reg(), | 2200 compiler->EmitEqualityRegConstCompare(left.reg(), |
| 2215 right.constant(), | 2201 right.constant(), |
| 2216 needs_number_check()); | 2202 needs_number_check()); |
| 2217 } else { | 2203 } else { |
| 2218 compiler->EmitEqualityRegRegCompare(left.reg(), | 2204 compiler->EmitEqualityRegRegCompare(left.reg(), |
| 2219 right.reg(), | 2205 right.reg(), |
| 2220 needs_number_check()); | 2206 needs_number_check()); |
| 2221 } | 2207 } |
| 2222 | 2208 |
| 2223 Register result = locs()->out().reg(); | 2209 Register result = locs()->out().reg(); |
| 2224 Label load_true, done; | |
| 2225 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE; | 2210 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE; |
| 2226 __ b(&load_true, true_condition); | 2211 __ LoadObject(result, Bool::True(), true_condition); |
| 2227 __ LoadObject(result, Bool::False()); | 2212 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
| 2228 __ b(&done); | |
| 2229 __ Bind(&load_true); | |
| 2230 __ LoadObject(result, Bool::True()); | |
| 2231 __ Bind(&done); | |
| 2232 } | 2213 } |
| 2233 | 2214 |
| 2234 | 2215 |
| 2235 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 2216 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 2236 BranchInstr* branch) { | 2217 BranchInstr* branch) { |
| 2237 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 2218 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 2238 Location left = locs()->in(0); | 2219 Location left = locs()->in(0); |
| 2239 Location right = locs()->in(1); | 2220 Location right = locs()->in(1); |
| 2240 if (left.IsConstant() && right.IsConstant()) { | 2221 if (left.IsConstant() && right.IsConstant()) { |
| 2241 // TODO(vegorov): should be eliminated earlier by constant propagation. | 2222 // TODO(vegorov): should be eliminated earlier by constant propagation. |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 2268 return LocationSummary::Make(1, | 2249 return LocationSummary::Make(1, |
| 2269 Location::RequiresRegister(), | 2250 Location::RequiresRegister(), |
| 2270 LocationSummary::kNoCall); | 2251 LocationSummary::kNoCall); |
| 2271 } | 2252 } |
| 2272 | 2253 |
| 2273 | 2254 |
| 2274 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2255 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2275 Register value = locs()->in(0).reg(); | 2256 Register value = locs()->in(0).reg(); |
| 2276 Register result = locs()->out().reg(); | 2257 Register result = locs()->out().reg(); |
| 2277 | 2258 |
| 2278 Label done; | |
| 2279 __ LoadObject(result, Bool::True()); | 2259 __ LoadObject(result, Bool::True()); |
| 2280 __ cmp(result, ShifterOperand(value)); | 2260 __ cmp(result, ShifterOperand(value)); |
| 2281 __ b(&done, NE); | 2261 __ LoadObject(result, Bool::False(), EQ); |
| 2282 __ LoadObject(result, Bool::False()); | |
| 2283 __ Bind(&done); | |
| 2284 } | 2262 } |
| 2285 | 2263 |
| 2286 | 2264 |
| 2287 LocationSummary* ChainContextInstr::MakeLocationSummary() const { | 2265 LocationSummary* ChainContextInstr::MakeLocationSummary() const { |
| 2288 UNIMPLEMENTED(); | 2266 UNIMPLEMENTED(); |
| 2289 return NULL; | 2267 return NULL; |
| 2290 } | 2268 } |
| 2291 | 2269 |
| 2292 | 2270 |
| 2293 void ChainContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2271 void ChainContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2338 &label, | 2316 &label, |
| 2339 PcDescriptors::kOther, | 2317 PcDescriptors::kOther, |
| 2340 locs()); | 2318 locs()); |
| 2341 __ Drop(2); // Discard type arguments and receiver. | 2319 __ Drop(2); // Discard type arguments and receiver. |
| 2342 } | 2320 } |
| 2343 | 2321 |
| 2344 } // namespace dart | 2322 } // namespace dart |
| 2345 | 2323 |
| 2346 #endif // defined TARGET_ARCH_ARM | 2324 #endif // defined TARGET_ARCH_ARM |
| 2347 | 2325 |
| OLD | NEW |