| 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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 case BELOW_EQUAL: return ABOVE_EQUAL; | 300 case BELOW_EQUAL: return ABOVE_EQUAL; |
| 301 case ABOVE: return BELOW; | 301 case ABOVE: return BELOW; |
| 302 case ABOVE_EQUAL: return BELOW_EQUAL; | 302 case ABOVE_EQUAL: return BELOW_EQUAL; |
| 303 default: | 303 default: |
| 304 UNIMPLEMENTED(); | 304 UNIMPLEMENTED(); |
| 305 return EQUAL; | 305 return EQUAL; |
| 306 } | 306 } |
| 307 } | 307 } |
| 308 | 308 |
| 309 | 309 |
| 310 static Condition NegateCondition(Condition condition) { |
| 311 switch (condition) { |
| 312 case EQUAL: return NOT_EQUAL; |
| 313 case NOT_EQUAL: return EQUAL; |
| 314 case LESS: return GREATER_EQUAL; |
| 315 case LESS_EQUAL: return GREATER; |
| 316 case GREATER: return LESS_EQUAL; |
| 317 case GREATER_EQUAL: return LESS; |
| 318 case BELOW: return ABOVE_EQUAL; |
| 319 case BELOW_EQUAL: return ABOVE; |
| 320 case ABOVE: return BELOW_EQUAL; |
| 321 case ABOVE_EQUAL: return BELOW; |
| 322 default: |
| 323 UNIMPLEMENTED(); |
| 324 return EQUAL; |
| 325 } |
| 326 } |
| 327 |
| 328 |
| 329 static void EmitBranchOnValue(FlowGraphCompiler* compiler, |
| 330 TargetEntryInstr* true_successor, |
| 331 TargetEntryInstr* false_successor, |
| 332 bool value) { |
| 333 if (value && !compiler->CanFallThroughTo(true_successor)) { |
| 334 __ jmp(compiler->GetJumpLabel(true_successor)); |
| 335 } else if (!value && !compiler->CanFallThroughTo(false_successor)) { |
| 336 __ jmp(compiler->GetJumpLabel(false_successor)); |
| 337 } |
| 338 } |
| 339 |
| 340 |
| 341 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| 342 TargetEntryInstr* true_successor, |
| 343 TargetEntryInstr* false_successor, |
| 344 Condition true_condition) { |
| 345 if (compiler->CanFallThroughTo(false_successor)) { |
| 346 // If the next block is the false successor, fall through to it. |
| 347 __ j(true_condition, compiler->GetJumpLabel(true_successor)); |
| 348 } else { |
| 349 // If the next block is not the false successor, branch to it. |
| 350 Condition false_condition = NegateCondition(true_condition); |
| 351 __ j(false_condition, compiler->GetJumpLabel(false_successor)); |
| 352 |
| 353 // Fall through or jump to the true successor. |
| 354 if (!compiler->CanFallThroughTo(true_successor)) { |
| 355 __ jmp(compiler->GetJumpLabel(true_successor)); |
| 356 } |
| 357 } |
| 358 } |
| 359 |
| 360 |
| 310 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 361 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 311 const LocationSummary& locs, | 362 const LocationSummary& locs, |
| 312 Token::Kind kind, | 363 Token::Kind kind, |
| 313 BranchInstr* branch) { | 364 BranchInstr* branch) { |
| 314 Location left = locs.in(0); | 365 Location left = locs.in(0); |
| 315 Location right = locs.in(1); | 366 Location right = locs.in(1); |
| 316 ASSERT(!left.IsConstant() || !right.IsConstant()); | 367 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 317 | 368 |
| 318 Condition true_condition = TokenKindToSmiCondition(kind); | 369 Condition true_condition = TokenKindToSmiCondition(kind); |
| 319 | 370 |
| 320 if (left.IsConstant()) { | 371 if (left.IsConstant()) { |
| 321 __ CompareObject(right.reg(), left.constant()); | 372 __ CompareObject(right.reg(), left.constant()); |
| 322 true_condition = FlipCondition(true_condition); | 373 true_condition = FlipCondition(true_condition); |
| 323 } else if (right.IsConstant()) { | 374 } else if (right.IsConstant()) { |
| 324 __ CompareObject(left.reg(), right.constant()); | 375 __ CompareObject(left.reg(), right.constant()); |
| 325 } else if (right.IsStackSlot()) { | 376 } else if (right.IsStackSlot()) { |
| 326 __ cmpl(left.reg(), right.ToStackSlotAddress()); | 377 __ cmpl(left.reg(), right.ToStackSlotAddress()); |
| 327 } else { | 378 } else { |
| 328 __ cmpl(left.reg(), right.reg()); | 379 __ cmpl(left.reg(), right.reg()); |
| 329 } | 380 } |
| 330 | 381 |
| 331 if (branch != NULL) { | 382 if (branch != NULL) { |
| 332 branch->EmitBranchOnCondition(compiler, true_condition); | 383 EmitBranchOnCondition(compiler, |
| 384 branch->true_successor(), |
| 385 branch->false_successor(), |
| 386 true_condition); |
| 333 } else { | 387 } else { |
| 334 Register result = locs.out().reg(); | 388 Register result = locs.out().reg(); |
| 335 Label done, is_true; | 389 Label done, is_true; |
| 336 __ j(true_condition, &is_true); | 390 __ j(true_condition, &is_true); |
| 337 __ LoadObject(result, Bool::False()); | 391 __ LoadObject(result, Bool::False()); |
| 338 __ jmp(&done); | 392 __ jmp(&done); |
| 339 __ Bind(&is_true); | 393 __ Bind(&is_true); |
| 340 __ LoadObject(result, Bool::True()); | 394 __ LoadObject(result, Bool::True()); |
| 341 __ Bind(&done); | 395 __ Bind(&done); |
| 342 } | 396 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 XmmRegister right = locs.in(1).fpu_reg(); | 447 XmmRegister right = locs.in(1).fpu_reg(); |
| 394 Register temp = locs.temp(0).reg(); | 448 Register temp = locs.temp(0).reg(); |
| 395 __ movaps(XMM0, left); | 449 __ movaps(XMM0, left); |
| 396 __ pcmpeqq(XMM0, right); | 450 __ pcmpeqq(XMM0, right); |
| 397 __ movd(temp, XMM0); | 451 __ movd(temp, XMM0); |
| 398 | 452 |
| 399 Condition true_condition = TokenKindToMintCondition(kind); | 453 Condition true_condition = TokenKindToMintCondition(kind); |
| 400 __ cmpl(temp, Immediate(-1)); | 454 __ cmpl(temp, Immediate(-1)); |
| 401 | 455 |
| 402 if (branch != NULL) { | 456 if (branch != NULL) { |
| 403 branch->EmitBranchOnCondition(compiler, true_condition); | 457 EmitBranchOnCondition(compiler, |
| 458 branch->true_successor(), |
| 459 branch->false_successor(), |
| 460 true_condition); |
| 404 } else { | 461 } else { |
| 405 Register result = locs.out().reg(); | 462 Register result = locs.out().reg(); |
| 406 Label done, is_true; | 463 Label done, is_true; |
| 407 __ j(true_condition, &is_true); | 464 __ j(true_condition, &is_true); |
| 408 __ LoadObject(result, Bool::False()); | 465 __ LoadObject(result, Bool::False()); |
| 409 __ jmp(&done); | 466 __ jmp(&done); |
| 410 __ Bind(&is_true); | 467 __ Bind(&is_true); |
| 411 __ LoadObject(result, Bool::True()); | 468 __ LoadObject(result, Bool::True()); |
| 412 __ Bind(&done); | 469 __ Bind(&done); |
| 413 } | 470 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 } else { | 515 } else { |
| 459 __ j(hi_cond, &is_true); | 516 __ j(hi_cond, &is_true); |
| 460 __ j(FlipCondition(hi_cond), &is_false); | 517 __ j(FlipCondition(hi_cond), &is_false); |
| 461 } | 518 } |
| 462 | 519 |
| 463 // If upper is equal, compare lower half. | 520 // If upper is equal, compare lower half. |
| 464 __ pextrd(left_tmp, left, Immediate(0)); | 521 __ pextrd(left_tmp, left, Immediate(0)); |
| 465 __ pextrd(right_tmp, right, Immediate(0)); | 522 __ pextrd(right_tmp, right, Immediate(0)); |
| 466 __ cmpl(left_tmp, right_tmp); | 523 __ cmpl(left_tmp, right_tmp); |
| 467 if (branch != NULL) { | 524 if (branch != NULL) { |
| 468 branch->EmitBranchOnCondition(compiler, lo_cond); | 525 EmitBranchOnCondition(compiler, |
| 526 branch->true_successor(), |
| 527 branch->false_successor(), |
| 528 lo_cond); |
| 469 } else { | 529 } else { |
| 470 Label done; | 530 Label done; |
| 471 __ j(lo_cond, &is_true); | 531 __ j(lo_cond, &is_true); |
| 472 __ Bind(&is_false); | 532 __ Bind(&is_false); |
| 473 __ LoadObject(result, Bool::False()); | 533 __ LoadObject(result, Bool::False()); |
| 474 __ jmp(&done); | 534 __ jmp(&done); |
| 475 __ Bind(&is_true); | 535 __ Bind(&is_true); |
| 476 __ LoadObject(result, Bool::True()); | 536 __ LoadObject(result, Bool::True()); |
| 477 __ Bind(&done); | 537 __ Bind(&done); |
| 478 } | 538 } |
| 479 } | 539 } |
| 480 | 540 |
| 481 | 541 |
| 482 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 542 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| 483 switch (kind) { | 543 switch (kind) { |
| 484 case Token::kEQ: return EQUAL; | 544 case Token::kEQ: return EQUAL; |
| 485 case Token::kNE: return NOT_EQUAL; | 545 case Token::kNE: return NOT_EQUAL; |
| 486 case Token::kLT: return BELOW; | 546 case Token::kLT: return BELOW; |
| 487 case Token::kGT: return ABOVE; | 547 case Token::kGT: return ABOVE; |
| 488 case Token::kLTE: return BELOW_EQUAL; | 548 case Token::kLTE: return BELOW_EQUAL; |
| 489 case Token::kGTE: return ABOVE_EQUAL; | 549 case Token::kGTE: return ABOVE_EQUAL; |
| 490 default: | 550 default: |
| 491 UNREACHABLE(); | 551 UNREACHABLE(); |
| 492 return OVERFLOW; | 552 return OVERFLOW; |
| 493 } | 553 } |
| 494 } | 554 } |
| 495 | 555 |
| 496 | 556 |
| 557 static void EmitDoubleCompareBranch(FlowGraphCompiler* compiler, |
| 558 Condition true_condition, |
| 559 FpuRegister left, |
| 560 FpuRegister right, |
| 561 BranchInstr* branch) { |
| 562 ASSERT(branch != NULL); |
| 563 __ comisd(left, right); |
| 564 BlockEntryInstr* nan_result = (true_condition == NOT_EQUAL) ? |
| 565 branch->true_successor() : branch->false_successor(); |
| 566 __ j(PARITY_EVEN, compiler->GetJumpLabel(nan_result)); |
| 567 EmitBranchOnCondition(compiler, |
| 568 branch->true_successor(), |
| 569 branch->false_successor(), |
| 570 true_condition); |
| 571 } |
| 572 |
| 573 |
| 574 |
| 575 static void EmitDoubleCompareBool(FlowGraphCompiler* compiler, |
| 576 Condition true_condition, |
| 577 FpuRegister left, |
| 578 FpuRegister right, |
| 579 Register result) { |
| 580 __ comisd(left, right); |
| 581 Label is_false, is_true, done; |
| 582 // x == NaN -> false, x != NaN -> true. |
| 583 Label* nan_label = (true_condition == NOT_EQUAL) ? &is_true : &is_false; |
| 584 __ j(PARITY_EVEN, nan_label, Assembler::kNearJump); |
| 585 __ j(true_condition, &is_true, Assembler::kNearJump); |
| 586 __ Bind(&is_false); |
| 587 __ LoadObject(result, Bool::False()); |
| 588 __ jmp(&done); |
| 589 __ Bind(&is_true); |
| 590 __ LoadObject(result, Bool::True()); |
| 591 __ Bind(&done); |
| 592 } |
| 593 |
| 594 |
| 497 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 595 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 498 const LocationSummary& locs, | 596 const LocationSummary& locs, |
| 499 Token::Kind kind, | 597 Token::Kind kind, |
| 500 BranchInstr* branch) { | 598 BranchInstr* branch) { |
| 501 XmmRegister left = locs.in(0).fpu_reg(); | 599 XmmRegister left = locs.in(0).fpu_reg(); |
| 502 XmmRegister right = locs.in(1).fpu_reg(); | 600 XmmRegister right = locs.in(1).fpu_reg(); |
| 503 | 601 |
| 504 Condition true_condition = TokenKindToDoubleCondition(kind); | 602 Condition true_condition = TokenKindToDoubleCondition(kind); |
| 505 if (branch != NULL) { | 603 if (branch != NULL) { |
| 506 compiler->EmitDoubleCompareBranch( | 604 EmitDoubleCompareBranch(compiler, true_condition, left, right, branch); |
| 507 true_condition, left, right, branch); | |
| 508 } else { | 605 } else { |
| 509 compiler->EmitDoubleCompareBool( | 606 EmitDoubleCompareBool(compiler, true_condition, |
| 510 true_condition, left, right, locs.out().reg()); | 607 left, right, locs.out().reg()); |
| 511 } | 608 } |
| 512 } | 609 } |
| 513 | 610 |
| 514 | 611 |
| 515 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 612 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 516 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 613 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 517 BranchInstr* kNoBranch = NULL; | 614 BranchInstr* kNoBranch = NULL; |
| 518 if (operation_cid() == kSmiCid) { | 615 if (operation_cid() == kSmiCid) { |
| 519 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch); | 616 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch); |
| 520 return; | 617 return; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 576 Register left = locs()->in(0).reg(); | 673 Register left = locs()->in(0).reg(); |
| 577 Location right = locs()->in(1); | 674 Location right = locs()->in(1); |
| 578 if (right.IsConstant()) { | 675 if (right.IsConstant()) { |
| 579 ASSERT(right.constant().IsSmi()); | 676 ASSERT(right.constant().IsSmi()); |
| 580 const int32_t imm = | 677 const int32_t imm = |
| 581 reinterpret_cast<int32_t>(right.constant().raw()); | 678 reinterpret_cast<int32_t>(right.constant().raw()); |
| 582 __ testl(left, Immediate(imm)); | 679 __ testl(left, Immediate(imm)); |
| 583 } else { | 680 } else { |
| 584 __ testl(left, right.reg()); | 681 __ testl(left, right.reg()); |
| 585 } | 682 } |
| 586 branch->EmitBranchOnCondition(compiler, branch_condition); | 683 EmitBranchOnCondition(compiler, |
| 684 branch->true_successor(), |
| 685 branch->false_successor(), |
| 686 branch_condition); |
| 587 } | 687 } |
| 588 | 688 |
| 589 | 689 |
| 590 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { | 690 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { |
| 591 const intptr_t kNumInputs = 2; | 691 const intptr_t kNumInputs = 2; |
| 592 const intptr_t kNumTemps = 0; | 692 const intptr_t kNumTemps = 0; |
| 593 if (operation_cid() == kMintCid) { | 693 if (operation_cid() == kMintCid) { |
| 594 const intptr_t kNumTemps = 2; | 694 const intptr_t kNumTemps = 2; |
| 595 LocationSummary* locs = | 695 LocationSummary* locs = |
| 596 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 696 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| (...skipping 3928 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4525 } | 4625 } |
| 4526 | 4626 |
| 4527 // We can fall through if the successor is the next block in the list. | 4627 // We can fall through if the successor is the next block in the list. |
| 4528 // Otherwise, we need a jump. | 4628 // Otherwise, we need a jump. |
| 4529 if (!compiler->CanFallThroughTo(successor())) { | 4629 if (!compiler->CanFallThroughTo(successor())) { |
| 4530 __ jmp(compiler->GetJumpLabel(successor())); | 4630 __ jmp(compiler->GetJumpLabel(successor())); |
| 4531 } | 4631 } |
| 4532 } | 4632 } |
| 4533 | 4633 |
| 4534 | 4634 |
| 4535 static Condition NegateCondition(Condition condition) { | |
| 4536 switch (condition) { | |
| 4537 case EQUAL: return NOT_EQUAL; | |
| 4538 case NOT_EQUAL: return EQUAL; | |
| 4539 case LESS: return GREATER_EQUAL; | |
| 4540 case LESS_EQUAL: return GREATER; | |
| 4541 case GREATER: return LESS_EQUAL; | |
| 4542 case GREATER_EQUAL: return LESS; | |
| 4543 case BELOW: return ABOVE_EQUAL; | |
| 4544 case BELOW_EQUAL: return ABOVE; | |
| 4545 case ABOVE: return BELOW_EQUAL; | |
| 4546 case ABOVE_EQUAL: return BELOW; | |
| 4547 default: | |
| 4548 UNIMPLEMENTED(); | |
| 4549 return EQUAL; | |
| 4550 } | |
| 4551 } | |
| 4552 | |
| 4553 | |
| 4554 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, | |
| 4555 bool value) { | |
| 4556 if (value && !compiler->CanFallThroughTo(true_successor())) { | |
| 4557 __ jmp(compiler->GetJumpLabel(true_successor())); | |
| 4558 } else if (!value && !compiler->CanFallThroughTo(false_successor())) { | |
| 4559 __ jmp(compiler->GetJumpLabel(false_successor())); | |
| 4560 } | |
| 4561 } | |
| 4562 | |
| 4563 | |
| 4564 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler, | |
| 4565 Condition true_condition) { | |
| 4566 if (compiler->CanFallThroughTo(false_successor())) { | |
| 4567 // If the next block is the false successor, fall through to it. | |
| 4568 __ j(true_condition, compiler->GetJumpLabel(true_successor())); | |
| 4569 } else { | |
| 4570 // If the next block is not the false successor, branch to it. | |
| 4571 Condition false_condition = NegateCondition(true_condition); | |
| 4572 __ j(false_condition, compiler->GetJumpLabel(false_successor())); | |
| 4573 | |
| 4574 // Fall through or jump to the true successor. | |
| 4575 if (!compiler->CanFallThroughTo(true_successor())) { | |
| 4576 __ jmp(compiler->GetJumpLabel(true_successor())); | |
| 4577 } | |
| 4578 } | |
| 4579 } | |
| 4580 | |
| 4581 | |
| 4582 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { | 4635 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { |
| 4583 return LocationSummary::Make(0, | 4636 return LocationSummary::Make(0, |
| 4584 Location::RequiresRegister(), | 4637 Location::RequiresRegister(), |
| 4585 LocationSummary::kNoCall); | 4638 LocationSummary::kNoCall); |
| 4586 } | 4639 } |
| 4587 | 4640 |
| 4588 | 4641 |
| 4589 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4642 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4590 __ MoveRegister(locs()->out().reg(), CTX); | 4643 __ MoveRegister(locs()->out().reg(), CTX); |
| 4591 } | 4644 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4648 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 4701 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 4649 BranchInstr* branch) { | 4702 BranchInstr* branch) { |
| 4650 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 4703 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 4651 Location left = locs()->in(0); | 4704 Location left = locs()->in(0); |
| 4652 Location right = locs()->in(1); | 4705 Location right = locs()->in(1); |
| 4653 if (left.IsConstant() && right.IsConstant()) { | 4706 if (left.IsConstant() && right.IsConstant()) { |
| 4654 // TODO(vegorov): should be eliminated earlier by constant propagation. | 4707 // TODO(vegorov): should be eliminated earlier by constant propagation. |
| 4655 const bool result = (kind() == Token::kEQ_STRICT) ? | 4708 const bool result = (kind() == Token::kEQ_STRICT) ? |
| 4656 left.constant().raw() == right.constant().raw() : | 4709 left.constant().raw() == right.constant().raw() : |
| 4657 left.constant().raw() != right.constant().raw(); | 4710 left.constant().raw() != right.constant().raw(); |
| 4658 branch->EmitBranchOnValue(compiler, result); | 4711 EmitBranchOnValue(compiler, |
| 4712 branch->true_successor(), |
| 4713 branch->false_successor(), |
| 4714 result); |
| 4659 return; | 4715 return; |
| 4660 } | 4716 } |
| 4661 if (left.IsConstant()) { | 4717 if (left.IsConstant()) { |
| 4662 compiler->EmitEqualityRegConstCompare(right.reg(), | 4718 compiler->EmitEqualityRegConstCompare(right.reg(), |
| 4663 left.constant(), | 4719 left.constant(), |
| 4664 needs_number_check(), | 4720 needs_number_check(), |
| 4665 token_pos()); | 4721 token_pos()); |
| 4666 } else if (right.IsConstant()) { | 4722 } else if (right.IsConstant()) { |
| 4667 compiler->EmitEqualityRegConstCompare(left.reg(), | 4723 compiler->EmitEqualityRegConstCompare(left.reg(), |
| 4668 right.constant(), | 4724 right.constant(), |
| 4669 needs_number_check(), | 4725 needs_number_check(), |
| 4670 token_pos()); | 4726 token_pos()); |
| 4671 } else { | 4727 } else { |
| 4672 compiler->EmitEqualityRegRegCompare(left.reg(), | 4728 compiler->EmitEqualityRegRegCompare(left.reg(), |
| 4673 right.reg(), | 4729 right.reg(), |
| 4674 needs_number_check(), | 4730 needs_number_check(), |
| 4675 token_pos()); | 4731 token_pos()); |
| 4676 } | 4732 } |
| 4677 | 4733 |
| 4678 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; | 4734 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
| 4679 branch->EmitBranchOnCondition(compiler, true_condition); | 4735 EmitBranchOnCondition(compiler, |
| 4680 } | 4736 branch->true_successor(), |
| 4681 | 4737 branch->false_successor(), |
| 4682 | 4738 true_condition); |
| 4683 static bool BindsToSmiConstant(Value* val, intptr_t* smi_value) { | |
| 4684 if (!val->BindsToConstant()) { | |
| 4685 return false; | |
| 4686 } | |
| 4687 | |
| 4688 const Object& bound_constant = val->BoundConstant(); | |
| 4689 if (!bound_constant.IsSmi()) { | |
| 4690 return false; | |
| 4691 } | |
| 4692 | |
| 4693 *smi_value = Smi::Cast(bound_constant).Value(); | |
| 4694 return true; | |
| 4695 } | 4739 } |
| 4696 | 4740 |
| 4697 | 4741 |
| 4698 // Detect pattern when one value is zero and another is a power of 2. | 4742 // Detect pattern when one value is zero and another is a power of 2. |
| 4699 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { | 4743 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
| 4700 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || | 4744 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
| 4701 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); | 4745 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); |
| 4702 } | 4746 } |
| 4703 | 4747 |
| 4704 | 4748 |
| 4705 bool IfThenElseInstr::Supports(ComparisonInstr* comparison, | |
| 4706 Value* v1, | |
| 4707 Value* v2) { | |
| 4708 if (!(comparison->IsStrictCompare() && | |
| 4709 !comparison->AsStrictCompare()->needs_number_check()) && | |
| 4710 !(comparison->IsEqualityCompare() && | |
| 4711 (comparison->AsEqualityCompare()->operation_cid() == kSmiCid))) { | |
| 4712 return false; | |
| 4713 } | |
| 4714 | |
| 4715 intptr_t v1_value, v2_value; | |
| 4716 | |
| 4717 if (!BindsToSmiConstant(v1, &v1_value) || | |
| 4718 !BindsToSmiConstant(v2, &v2_value)) { | |
| 4719 return false; | |
| 4720 } | |
| 4721 | |
| 4722 return true; | |
| 4723 } | |
| 4724 | |
| 4725 | |
| 4726 LocationSummary* IfThenElseInstr::MakeLocationSummary() const { | 4749 LocationSummary* IfThenElseInstr::MakeLocationSummary() const { |
| 4727 const intptr_t kNumInputs = 2; | 4750 const intptr_t kNumInputs = 2; |
| 4728 const intptr_t kNumTemps = 0; | 4751 const intptr_t kNumTemps = 0; |
| 4729 LocationSummary* locs = | 4752 LocationSummary* locs = |
| 4730 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4753 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4731 locs->set_in(0, Location::RegisterOrConstant(left())); | 4754 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 4732 locs->set_in(1, Location::RegisterOrConstant(right())); | 4755 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 4733 // TODO(vegorov): support byte register constraints in the register allocator. | 4756 // TODO(vegorov): support byte register constraints in the register allocator. |
| 4734 locs->set_out(Location::RegisterLocation(EDX)); | 4757 locs->set_out(Location::RegisterLocation(EDX)); |
| 4735 return locs; | 4758 return locs; |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4921 PcDescriptors::kOther, | 4944 PcDescriptors::kOther, |
| 4922 locs()); | 4945 locs()); |
| 4923 __ Drop(2); // Discard type arguments and receiver. | 4946 __ Drop(2); // Discard type arguments and receiver. |
| 4924 } | 4947 } |
| 4925 | 4948 |
| 4926 } // namespace dart | 4949 } // namespace dart |
| 4927 | 4950 |
| 4928 #undef __ | 4951 #undef __ |
| 4929 | 4952 |
| 4930 #endif // defined TARGET_ARCH_IA32 | 4953 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |