| 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_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
| 6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 // A finally clause may leave a previously pushed return value if it | 87 // A finally clause may leave a previously pushed return value if it |
| 88 // has its own return instruction. Method that have finally are currently | 88 // has its own return instruction. Method that have finally are currently |
| 89 // not optimized. | 89 // not optimized. |
| 90 if (!compiler->HasFinally()) { | 90 if (!compiler->HasFinally()) { |
| 91 Label stack_ok; | 91 Label stack_ok; |
| 92 __ Comment("Stack Check"); | 92 __ Comment("Stack Check"); |
| 93 __ TraceSimMsg("Stack Check"); | 93 __ TraceSimMsg("Stack Check"); |
| 94 const intptr_t fp_sp_dist = | 94 const intptr_t fp_sp_dist = |
| 95 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; | 95 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; |
| 96 ASSERT(fp_sp_dist <= 0); | 96 ASSERT(fp_sp_dist <= 0); |
| 97 __ subu(TMP1, SP, FP); | 97 __ subu(CMPRES1, SP, FP); |
| 98 | 98 |
| 99 __ BranchEqual(TMP1, fp_sp_dist, &stack_ok); | 99 __ BranchEqual(CMPRES1, fp_sp_dist, &stack_ok); |
| 100 __ break_(0); | 100 __ break_(0); |
| 101 | 101 |
| 102 __ Bind(&stack_ok); | 102 __ Bind(&stack_ok); |
| 103 } | 103 } |
| 104 #endif | 104 #endif |
| 105 // This sequence is patched by a debugger breakpoint. There is no need for | 105 // This sequence is patched by a debugger breakpoint. There is no need for |
| 106 // extra NOP instructions here because the sequence patched in for a | 106 // extra NOP instructions here because the sequence patched in for a |
| 107 // breakpoint is shorter than the sequence here. | 107 // breakpoint is shorter than the sequence here. |
| 108 __ LeaveDartFrameAndReturn(); | 108 __ LeaveDartFrameAndReturn(); |
| 109 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 109 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 } | 352 } |
| 353 const int kNumberOfArguments = 2; | 353 const int kNumberOfArguments = 2; |
| 354 const Array& kNoArgumentNames = Object::null_array(); | 354 const Array& kNoArgumentNames = Object::null_array(); |
| 355 const int kNumArgumentsChecked = 2; | 355 const int kNumArgumentsChecked = 2; |
| 356 | 356 |
| 357 __ TraceSimMsg("EmitEqualityAsInstanceCall"); | 357 __ TraceSimMsg("EmitEqualityAsInstanceCall"); |
| 358 __ Comment("EmitEqualityAsInstanceCall"); | 358 __ Comment("EmitEqualityAsInstanceCall"); |
| 359 Label check_identity; | 359 Label check_identity; |
| 360 __ lw(A1, Address(SP, 1 * kWordSize)); | 360 __ lw(A1, Address(SP, 1 * kWordSize)); |
| 361 __ lw(A0, Address(SP, 0 * kWordSize)); | 361 __ lw(A0, Address(SP, 0 * kWordSize)); |
| 362 __ LoadImmediate(TMP, reinterpret_cast<int32_t>(Object::null())); | 362 __ LoadImmediate(CMPRES1, reinterpret_cast<int32_t>(Object::null())); |
| 363 __ beq(A1, TMP, &check_identity); | 363 __ beq(A1, CMPRES1, &check_identity); |
| 364 __ beq(A0, TMP, &check_identity); | 364 __ beq(A0, CMPRES1, &check_identity); |
| 365 | 365 |
| 366 ICData& equality_ic_data = ICData::ZoneHandle(); | 366 ICData& equality_ic_data = ICData::ZoneHandle(); |
| 367 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { | 367 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { |
| 368 ASSERT(!original_ic_data.IsNull()); | 368 ASSERT(!original_ic_data.IsNull()); |
| 369 if (original_ic_data.NumberOfChecks() == 0) { | 369 if (original_ic_data.NumberOfChecks() == 0) { |
| 370 // IC call for reoptimization populates original ICData. | 370 // IC call for reoptimization populates original ICData. |
| 371 equality_ic_data = original_ic_data.raw(); | 371 equality_ic_data = original_ic_data.raw(); |
| 372 } else { | 372 } else { |
| 373 // Megamorphic call. | 373 // Megamorphic call. |
| 374 equality_ic_data = original_ic_data.AsUnaryClassChecks(); | 374 equality_ic_data = original_ic_data.AsUnaryClassChecks(); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 439 | 439 |
| 440 static void LoadValueCid(FlowGraphCompiler* compiler, | 440 static void LoadValueCid(FlowGraphCompiler* compiler, |
| 441 Register value_cid_reg, | 441 Register value_cid_reg, |
| 442 Register value_reg, | 442 Register value_reg, |
| 443 Label* value_is_smi = NULL) { | 443 Label* value_is_smi = NULL) { |
| 444 __ TraceSimMsg("LoadValueCid"); | 444 __ TraceSimMsg("LoadValueCid"); |
| 445 Label done; | 445 Label done; |
| 446 if (value_is_smi == NULL) { | 446 if (value_is_smi == NULL) { |
| 447 __ LoadImmediate(value_cid_reg, kSmiCid); | 447 __ LoadImmediate(value_cid_reg, kSmiCid); |
| 448 } | 448 } |
| 449 __ andi(TMP1, value_reg, Immediate(kSmiTagMask)); | 449 __ andi(CMPRES1, value_reg, Immediate(kSmiTagMask)); |
| 450 if (value_is_smi == NULL) { | 450 if (value_is_smi == NULL) { |
| 451 __ beq(TMP1, ZR, &done); | 451 __ beq(CMPRES1, ZR, &done); |
| 452 } else { | 452 } else { |
| 453 __ beq(TMP1, ZR, value_is_smi); | 453 __ beq(CMPRES1, ZR, value_is_smi); |
| 454 } | 454 } |
| 455 __ LoadClassId(value_cid_reg, value_reg); | 455 __ LoadClassId(value_cid_reg, value_reg); |
| 456 __ Bind(&done); | 456 __ Bind(&done); |
| 457 } | 457 } |
| 458 | 458 |
| 459 | 459 |
| 460 static Condition TokenKindToSmiCondition(Token::Kind kind) { | 460 static Condition TokenKindToSmiCondition(Token::Kind kind) { |
| 461 switch (kind) { | 461 switch (kind) { |
| 462 case Token::kEQ: return EQ; | 462 case Token::kEQ: return EQ; |
| 463 case Token::kNE: return NE; | 463 case Token::kNE: return NE; |
| 464 case Token::kLT: return LT; | 464 case Token::kLT: return LT; |
| 465 case Token::kGT: return GT; | 465 case Token::kGT: return GT; |
| 466 case Token::kLTE: return LE; | 466 case Token::kLTE: return LE; |
| 467 case Token::kGTE: return GE; | 467 case Token::kGTE: return GE; |
| 468 default: | 468 default: |
| 469 UNREACHABLE(); | 469 UNREACHABLE(); |
| 470 return VS; | 470 return VS; |
| 471 } | 471 } |
| 472 } | 472 } |
| 473 | 473 |
| 474 | 474 |
| 475 // Branches on condition c assuming comparison results in CMPRES and TMP1. | 475 // Branches on condition c assuming comparison results in CMPRES and CMPRES2. |
| 476 static void EmitBranchAfterCompare( | 476 static void EmitBranchAfterCompare( |
| 477 FlowGraphCompiler* compiler, Condition c, Label* is_true) { | 477 FlowGraphCompiler* compiler, Condition c, Label* is_true) { |
| 478 switch (c) { | 478 switch (c) { |
| 479 case EQ: __ beq(CMPRES, TMP1, is_true); break; | 479 case EQ: __ beq(CMPRES1, CMPRES2, is_true); break; |
| 480 case NE: __ bne(CMPRES, TMP1, is_true); break; | 480 case NE: __ bne(CMPRES1, CMPRES2, is_true); break; |
| 481 case GT: __ bne(TMP1, ZR, is_true); break; | 481 case GT: __ bne(CMPRES2, ZR, is_true); break; |
| 482 case GE: __ beq(CMPRES, ZR, is_true); break; | 482 case GE: __ beq(CMPRES1, ZR, is_true); break; |
| 483 case LT: __ bne(CMPRES, ZR, is_true); break; | 483 case LT: __ bne(CMPRES1, ZR, is_true); break; |
| 484 case LE: __ beq(TMP1, ZR, is_true); break; | 484 case LE: __ beq(CMPRES2, ZR, is_true); break; |
| 485 default: | 485 default: |
| 486 UNREACHABLE(); | 486 UNREACHABLE(); |
| 487 break; | 487 break; |
| 488 } | 488 } |
| 489 } | 489 } |
| 490 | 490 |
| 491 | 491 |
| 492 // A1: left, also on stack. | 492 // A1: left, also on stack. |
| 493 // A0: right, also on stack. | 493 // A0: right, also on stack. |
| 494 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, | 494 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, |
| (...skipping 30 matching lines...) Expand all Loading... |
| 525 Label next_test; | 525 Label next_test; |
| 526 if (i < len - 1) { | 526 if (i < len - 1) { |
| 527 __ BranchNotEqual(temp, ic_data.GetReceiverClassIdAt(i), &next_test); | 527 __ BranchNotEqual(temp, ic_data.GetReceiverClassIdAt(i), &next_test); |
| 528 } else { | 528 } else { |
| 529 __ BranchNotEqual(temp, ic_data.GetReceiverClassIdAt(i), deopt); | 529 __ BranchNotEqual(temp, ic_data.GetReceiverClassIdAt(i), deopt); |
| 530 } | 530 } |
| 531 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i)); | 531 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i)); |
| 532 if (target.Owner() == object_store->object_class()) { | 532 if (target.Owner() == object_store->object_class()) { |
| 533 // Object.== is same as ===. | 533 // Object.== is same as ===. |
| 534 __ Drop(2); | 534 __ Drop(2); |
| 535 __ slt(CMPRES, left, right); | 535 __ slt(CMPRES1, left, right); |
| 536 __ slt(TMP1, right, left); | 536 __ slt(CMPRES2, right, left); |
| 537 if (branch != NULL) { | 537 if (branch != NULL) { |
| 538 branch->EmitBranchOnCondition(compiler, cond); | 538 branch->EmitBranchOnCondition(compiler, cond); |
| 539 } else { | 539 } else { |
| 540 Register result = locs->out().reg(); | 540 Register result = locs->out().reg(); |
| 541 Label load_true; | 541 Label load_true; |
| 542 EmitBranchAfterCompare(compiler, cond, &load_true); | 542 EmitBranchAfterCompare(compiler, cond, &load_true); |
| 543 __ LoadObject(result, Bool::False()); | 543 __ LoadObject(result, Bool::False()); |
| 544 __ b(&done); | 544 __ b(&done); |
| 545 __ Bind(&load_true); | 545 __ Bind(&load_true); |
| 546 __ LoadObject(result, Bool::True()); | 546 __ LoadObject(result, Bool::True()); |
| 547 } | 547 } |
| 548 } else { | 548 } else { |
| 549 const int kNumberOfArguments = 2; | 549 const int kNumberOfArguments = 2; |
| 550 const Array& kNoArgumentNames = Object::null_array(); | 550 const Array& kNoArgumentNames = Object::null_array(); |
| 551 compiler->GenerateStaticCall(deopt_id, | 551 compiler->GenerateStaticCall(deopt_id, |
| 552 token_pos, | 552 token_pos, |
| 553 target, | 553 target, |
| 554 kNumberOfArguments, | 554 kNumberOfArguments, |
| 555 kNoArgumentNames, | 555 kNoArgumentNames, |
| 556 locs); | 556 locs); |
| 557 if (branch == NULL) { | 557 if (branch == NULL) { |
| 558 if (kind == Token::kNE) { | 558 if (kind == Token::kNE) { |
| 559 Label is_true; | 559 Label is_true; |
| 560 __ CompareObject(CMPRES, TMP1, V0, Bool::True()); | 560 __ CompareObject(CMPRES1, CMPRES2, V0, Bool::True()); |
| 561 __ beq(CMPRES, TMP1, &is_true); | 561 __ beq(CMPRES, CMPRES2, &is_true); |
| 562 __ LoadObject(V0, Bool::True()); | 562 __ LoadObject(V0, Bool::True()); |
| 563 __ b(&done); | 563 __ b(&done); |
| 564 __ Bind(&is_true); | 564 __ Bind(&is_true); |
| 565 __ LoadObject(V0, Bool::False()); | 565 __ LoadObject(V0, Bool::False()); |
| 566 } | 566 } |
| 567 } else { | 567 } else { |
| 568 if (branch->is_checked()) { | 568 if (branch->is_checked()) { |
| 569 EmitAssertBoolean(V0, token_pos, deopt_id, locs, compiler); | 569 EmitAssertBoolean(V0, token_pos, deopt_id, locs, compiler); |
| 570 } | 570 } |
| 571 __ CompareObject(CMPRES, TMP1, V0, Bool::True()); | 571 __ CompareObject(CMPRES1, CMPRES2, V0, Bool::True()); |
| 572 branch->EmitBranchOnCondition(compiler, cond); | 572 branch->EmitBranchOnCondition(compiler, cond); |
| 573 } | 573 } |
| 574 } | 574 } |
| 575 if (i < len - 1) { | 575 if (i < len - 1) { |
| 576 __ b(&done); | 576 __ b(&done); |
| 577 __ Bind(&next_test); | 577 __ Bind(&next_test); |
| 578 } | 578 } |
| 579 } | 579 } |
| 580 __ Bind(&done); | 580 __ Bind(&done); |
| 581 } | 581 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 593 Register right = locs.in(1).reg(); | 593 Register right = locs.in(1).reg(); |
| 594 Register temp = locs.temp(0).reg(); | 594 Register temp = locs.temp(0).reg(); |
| 595 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality); | 595 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality); |
| 596 | 596 |
| 597 __ Comment("CheckedStrictEqual"); | 597 __ Comment("CheckedStrictEqual"); |
| 598 | 598 |
| 599 __ andi(CMPRES, left, Immediate(kSmiTagMask)); | 599 __ andi(CMPRES, left, Immediate(kSmiTagMask)); |
| 600 __ beq(CMPRES, ZR, deopt); | 600 __ beq(CMPRES, ZR, deopt); |
| 601 // 'left' is not Smi. | 601 // 'left' is not Smi. |
| 602 Label identity_compare; | 602 Label identity_compare; |
| 603 __ LoadImmediate(TMP, reinterpret_cast<int32_t>(Object::null())); | 603 __ LoadImmediate(CMPRES1, reinterpret_cast<int32_t>(Object::null())); |
| 604 __ beq(right, TMP, &identity_compare); | 604 __ beq(right, CMPRES1, &identity_compare); |
| 605 __ beq(left, TMP, &identity_compare); | 605 __ beq(left, CMPRES1, &identity_compare); |
| 606 | 606 |
| 607 __ LoadClassId(temp, left); | 607 __ LoadClassId(temp, left); |
| 608 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); | 608 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); |
| 609 const intptr_t len = ic_data.NumberOfChecks(); | 609 const intptr_t len = ic_data.NumberOfChecks(); |
| 610 for (intptr_t i = 0; i < len; i++) { | 610 for (intptr_t i = 0; i < len; i++) { |
| 611 if (i == (len - 1)) { | 611 if (i == (len - 1)) { |
| 612 __ BranchNotEqual(temp, ic_data.GetReceiverClassIdAt(i), deopt); | 612 __ BranchNotEqual(temp, ic_data.GetReceiverClassIdAt(i), deopt); |
| 613 } else { | 613 } else { |
| 614 __ BranchEqual(temp, ic_data.GetReceiverClassIdAt(i), &identity_compare); | 614 __ BranchEqual(temp, ic_data.GetReceiverClassIdAt(i), &identity_compare); |
| 615 } | 615 } |
| 616 } | 616 } |
| 617 __ Bind(&identity_compare); | 617 __ Bind(&identity_compare); |
| 618 __ subu(CMPRES, left, right); | 618 __ subu(CMPRES1, left, right); |
| 619 if (branch == NULL) { | 619 if (branch == NULL) { |
| 620 Label done, is_equal; | 620 Label done, is_equal; |
| 621 Register result = locs.out().reg(); | 621 Register result = locs.out().reg(); |
| 622 __ beq(CMPRES, ZR, &is_equal); | 622 __ beq(CMPRES, ZR, &is_equal); |
| 623 // Not equal. | 623 // Not equal. |
| 624 __ LoadObject(result, | 624 __ LoadObject(result, |
| 625 (kind == Token::kEQ) ? Bool::False() : Bool::True()); | 625 (kind == Token::kEQ) ? Bool::False() : Bool::True()); |
| 626 __ b(&done); | 626 __ b(&done); |
| 627 __ Bind(&is_equal); | 627 __ Bind(&is_equal); |
| 628 __ LoadObject(result, | 628 __ LoadObject(result, |
| 629 (kind == Token::kEQ) ? Bool::True() : Bool::False()); | 629 (kind == Token::kEQ) ? Bool::True() : Bool::False()); |
| 630 __ Bind(&done); | 630 __ Bind(&done); |
| 631 | 631 |
| 632 } else { | 632 } else { |
| 633 Condition cond = TokenKindToSmiCondition(kind); | 633 Condition cond = TokenKindToSmiCondition(kind); |
| 634 __ mov(TMP, ZR); | 634 __ mov(CMPRES2, ZR); |
| 635 branch->EmitBranchOnCondition(compiler, cond); | 635 branch->EmitBranchOnCondition(compiler, cond); |
| 636 } | 636 } |
| 637 } | 637 } |
| 638 | 638 |
| 639 | 639 |
| 640 // First test if receiver is NULL, in which case === is applied. | 640 // First test if receiver is NULL, in which case === is applied. |
| 641 // If type feedback was provided (lists of <class-id, target>), do a | 641 // If type feedback was provided (lists of <class-id, target>), do a |
| 642 // type by type check (either === or static call to the operator. | 642 // type by type check (either === or static call to the operator. |
| 643 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, | 643 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, |
| 644 LocationSummary* locs, | 644 LocationSummary* locs, |
| 645 Token::Kind kind, | 645 Token::Kind kind, |
| 646 BranchInstr* branch, | 646 BranchInstr* branch, |
| 647 const ICData& ic_data, | 647 const ICData& ic_data, |
| 648 intptr_t deopt_id, | 648 intptr_t deopt_id, |
| 649 intptr_t token_pos) { | 649 intptr_t token_pos) { |
| 650 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 650 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 651 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); | 651 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); |
| 652 Register left = locs->in(0).reg(); | 652 Register left = locs->in(0).reg(); |
| 653 Register right = locs->in(1).reg(); | 653 Register right = locs->in(1).reg(); |
| 654 Label done, identity_compare, non_null_compare; | 654 Label done, identity_compare, non_null_compare; |
| 655 __ TraceSimMsg("EmitGenericEqualityCompare"); | 655 __ TraceSimMsg("EmitGenericEqualityCompare"); |
| 656 __ Comment("EmitGenericEqualityCompare"); | 656 __ Comment("EmitGenericEqualityCompare"); |
| 657 __ LoadImmediate(TMP, reinterpret_cast<int32_t>(Object::null())); | 657 __ LoadImmediate(CMPRES1, reinterpret_cast<int32_t>(Object::null())); |
| 658 __ beq(right, TMP, &identity_compare); | 658 __ beq(right, CMPRES1, &identity_compare); |
| 659 __ bne(left, TMP, &non_null_compare); | 659 __ bne(left, CMPRES1, &non_null_compare); |
| 660 | 660 |
| 661 // Comparison with NULL is "===". | 661 // Comparison with NULL is "===". |
| 662 __ Bind(&identity_compare); | 662 __ Bind(&identity_compare); |
| 663 Condition cond = TokenKindToSmiCondition(kind); | 663 Condition cond = TokenKindToSmiCondition(kind); |
| 664 __ slt(CMPRES, left, right); | 664 __ slt(CMPRES1, left, right); |
| 665 __ slt(TMP1, right, left); | 665 __ slt(CMPRES2, right, left); |
| 666 if (branch != NULL) { | 666 if (branch != NULL) { |
| 667 branch->EmitBranchOnCondition(compiler, cond); | 667 branch->EmitBranchOnCondition(compiler, cond); |
| 668 } else { | 668 } else { |
| 669 Register result = locs->out().reg(); | 669 Register result = locs->out().reg(); |
| 670 Label load_true; | 670 Label load_true; |
| 671 EmitBranchAfterCompare(compiler, cond, &load_true); | 671 EmitBranchAfterCompare(compiler, cond, &load_true); |
| 672 __ LoadObject(result, Bool::False()); | 672 __ LoadObject(result, Bool::False()); |
| 673 __ b(&done); | 673 __ b(&done); |
| 674 __ Bind(&load_true); | 674 __ Bind(&load_true); |
| 675 __ LoadObject(result, Bool::True()); | 675 __ LoadObject(result, Bool::True()); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 708 BranchInstr* branch) { | 708 BranchInstr* branch) { |
| 709 __ TraceSimMsg("EmitSmiComparisonOp"); | 709 __ TraceSimMsg("EmitSmiComparisonOp"); |
| 710 __ Comment("EmitSmiComparisonOp"); | 710 __ Comment("EmitSmiComparisonOp"); |
| 711 Location left = locs.in(0); | 711 Location left = locs.in(0); |
| 712 Location right = locs.in(1); | 712 Location right = locs.in(1); |
| 713 ASSERT(!left.IsConstant() || !right.IsConstant()); | 713 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 714 | 714 |
| 715 Condition true_condition = TokenKindToSmiCondition(kind); | 715 Condition true_condition = TokenKindToSmiCondition(kind); |
| 716 | 716 |
| 717 if (left.IsConstant()) { | 717 if (left.IsConstant()) { |
| 718 __ CompareObject(CMPRES, TMP1, right.reg(), left.constant()); | 718 __ CompareObject(CMPRES1, CMPRES2, right.reg(), left.constant()); |
| 719 true_condition = FlipCondition(true_condition); | 719 true_condition = FlipCondition(true_condition); |
| 720 } else if (right.IsConstant()) { | 720 } else if (right.IsConstant()) { |
| 721 __ CompareObject(CMPRES, TMP1, left.reg(), right.constant()); | 721 __ CompareObject(CMPRES1, CMPRES2, left.reg(), right.constant()); |
| 722 } else { | 722 } else { |
| 723 __ slt(CMPRES, left.reg(), right.reg()); | 723 __ slt(CMPRES1, left.reg(), right.reg()); |
| 724 __ slt(TMP1, right.reg(), left.reg()); | 724 __ slt(CMPRES2, right.reg(), left.reg()); |
| 725 } | 725 } |
| 726 | 726 |
| 727 if (branch != NULL) { | 727 if (branch != NULL) { |
| 728 branch->EmitBranchOnCondition(compiler, true_condition); | 728 branch->EmitBranchOnCondition(compiler, true_condition); |
| 729 } else { | 729 } else { |
| 730 Register result = locs.out().reg(); | 730 Register result = locs.out().reg(); |
| 731 Label done, is_true; | 731 Label done, is_true; |
| 732 EmitBranchAfterCompare(compiler, true_condition, &is_true); | 732 EmitBranchAfterCompare(compiler, true_condition, &is_true); |
| 733 __ LoadObject(result, Bool::False()); | 733 __ LoadObject(result, Bool::False()); |
| 734 __ b(&done); | 734 __ b(&done); |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 871 EmitEqualityAsInstanceCall(compiler, | 871 EmitEqualityAsInstanceCall(compiler, |
| 872 deopt_id(), | 872 deopt_id(), |
| 873 token_pos(), | 873 token_pos(), |
| 874 Token::kEQ, // kNE reverse occurs at branch. | 874 Token::kEQ, // kNE reverse occurs at branch. |
| 875 locs(), | 875 locs(), |
| 876 *ic_data()); | 876 *ic_data()); |
| 877 if (branch->is_checked()) { | 877 if (branch->is_checked()) { |
| 878 EmitAssertBoolean(V0, token_pos(), deopt_id(), locs(), compiler); | 878 EmitAssertBoolean(V0, token_pos(), deopt_id(), locs(), compiler); |
| 879 } | 879 } |
| 880 Condition branch_condition = (kind() == Token::kNE) ? NE : EQ; | 880 Condition branch_condition = (kind() == Token::kNE) ? NE : EQ; |
| 881 __ CompareObject(CMPRES, TMP1, V0, Bool::True()); | 881 __ CompareObject(CMPRES1, CMPRES2, V0, Bool::True()); |
| 882 branch->EmitBranchOnCondition(compiler, branch_condition); | 882 branch->EmitBranchOnCondition(compiler, branch_condition); |
| 883 } | 883 } |
| 884 | 884 |
| 885 | 885 |
| 886 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { | 886 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { |
| 887 const intptr_t kNumInputs = 2; | 887 const intptr_t kNumInputs = 2; |
| 888 const intptr_t kNumTemps = 0; | 888 const intptr_t kNumTemps = 0; |
| 889 if (operation_cid() == kMintCid) { | 889 if (operation_cid() == kMintCid) { |
| 890 const intptr_t kNumTemps = 2; | 890 const intptr_t kNumTemps = 2; |
| 891 LocationSummary* locs = | 891 LocationSummary* locs = |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1011 } | 1011 } |
| 1012 if (operation_cid() == kMintCid) { | 1012 if (operation_cid() == kMintCid) { |
| 1013 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch); | 1013 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch); |
| 1014 return; | 1014 return; |
| 1015 } | 1015 } |
| 1016 if (operation_cid() == kDoubleCid) { | 1016 if (operation_cid() == kDoubleCid) { |
| 1017 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); | 1017 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); |
| 1018 return; | 1018 return; |
| 1019 } | 1019 } |
| 1020 EmitNativeCode(compiler); | 1020 EmitNativeCode(compiler); |
| 1021 __ CompareObject(CMPRES, TMP1, V0, Bool::True()); | 1021 __ CompareObject(CMPRES1, CMPRES2, V0, Bool::True()); |
| 1022 branch->EmitBranchOnCondition(compiler, EQ); | 1022 branch->EmitBranchOnCondition(compiler, EQ); |
| 1023 } | 1023 } |
| 1024 | 1024 |
| 1025 | 1025 |
| 1026 LocationSummary* NativeCallInstr::MakeLocationSummary() const { | 1026 LocationSummary* NativeCallInstr::MakeLocationSummary() const { |
| 1027 const intptr_t kNumInputs = 0; | 1027 const intptr_t kNumInputs = 0; |
| 1028 const intptr_t kNumTemps = 3; | 1028 const intptr_t kNumTemps = 3; |
| 1029 LocationSummary* locs = | 1029 LocationSummary* locs = |
| 1030 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1030 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1031 locs->set_temp(0, Location::RegisterLocation(A1)); | 1031 locs->set_temp(0, Location::RegisterLocation(A1)); |
| (...skipping 592 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1624 | 1624 |
| 1625 if (value_cid == kDynamicCid) { | 1625 if (value_cid == kDynamicCid) { |
| 1626 if (value_cid_reg == kNoRegister) { | 1626 if (value_cid_reg == kNoRegister) { |
| 1627 ASSERT(!compiler->is_optimizing()); | 1627 ASSERT(!compiler->is_optimizing()); |
| 1628 value_cid_reg = A1; | 1628 value_cid_reg = A1; |
| 1629 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg)); | 1629 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg)); |
| 1630 } | 1630 } |
| 1631 | 1631 |
| 1632 LoadValueCid(compiler, value_cid_reg, value_reg); | 1632 LoadValueCid(compiler, value_cid_reg, value_reg); |
| 1633 | 1633 |
| 1634 __ lw(TMP1, field_cid_operand); | 1634 __ lw(CMPRES1, field_cid_operand); |
| 1635 __ beq(value_cid_reg, TMP1, &ok); | 1635 __ beq(value_cid_reg, CMPRES1, &ok); |
| 1636 __ lw(TMP1, field_nullability_operand); | 1636 __ lw(TMP1, field_nullability_operand); |
| 1637 __ subu(CMPRES, value_cid_reg, TMP1); | 1637 __ subu(CMPRES, value_cid_reg, TMP1); |
| 1638 } else if (value_cid == kNullCid) { | 1638 } else if (value_cid == kNullCid) { |
| 1639 // TODO(regis): TMP1 may conflict. Revisit. | 1639 // TODO(regis): TMP1 may conflict. Revisit. |
| 1640 __ lw(TMP1, field_nullability_operand); | 1640 __ lw(TMP1, field_nullability_operand); |
| 1641 __ LoadImmediate(CMPRES, value_cid); | 1641 __ LoadImmediate(CMPRES, value_cid); |
| 1642 __ subu(CMPRES, TMP1, CMPRES); | 1642 __ subu(CMPRES, TMP1, CMPRES); |
| 1643 } else { | 1643 } else { |
| 1644 // TODO(regis): TMP1 may conflict. Revisit. | 1644 // TODO(regis): TMP1 may conflict. Revisit. |
| 1645 __ lw(TMP1, field_cid_operand); | 1645 __ lw(TMP1, field_cid_operand); |
| 1646 __ LoadImmediate(CMPRES, value_cid); | 1646 __ LoadImmediate(CMPRES, value_cid); |
| 1647 __ subu(CMPRES, TMP1, CMPRES); | 1647 __ subu(CMPRES, TMP1, CMPRES); |
| 1648 } | 1648 } |
| 1649 __ beq(CMPRES, ZR, &ok); | 1649 __ beq(CMPRES, ZR, &ok); |
| 1650 | 1650 |
| 1651 __ lw(TMP1, field_cid_operand); | 1651 __ lw(CMPRES1, field_cid_operand); |
| 1652 __ BranchNotEqual(TMP1, kIllegalCid, fail); | 1652 __ BranchNotEqual(CMPRES1, kIllegalCid, fail); |
| 1653 | 1653 |
| 1654 if (value_cid == kDynamicCid) { | 1654 if (value_cid == kDynamicCid) { |
| 1655 __ sw(value_cid_reg, field_cid_operand); | 1655 __ sw(value_cid_reg, field_cid_operand); |
| 1656 __ sw(value_cid_reg, field_nullability_operand); | 1656 __ sw(value_cid_reg, field_nullability_operand); |
| 1657 } else { | 1657 } else { |
| 1658 __ LoadImmediate(TMP1, value_cid); | 1658 __ LoadImmediate(TMP1, value_cid); |
| 1659 __ sw(TMP1, field_cid_operand); | 1659 __ sw(TMP1, field_cid_operand); |
| 1660 __ sw(TMP1, field_nullability_operand); | 1660 __ sw(TMP1, field_nullability_operand); |
| 1661 } | 1661 } |
| 1662 | 1662 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1697 ASSERT(!compiler->is_optimizing()); | 1697 ASSERT(!compiler->is_optimizing()); |
| 1698 return; | 1698 return; |
| 1699 } | 1699 } |
| 1700 } | 1700 } |
| 1701 } | 1701 } |
| 1702 | 1702 |
| 1703 if (deopt == NULL) { | 1703 if (deopt == NULL) { |
| 1704 ASSERT(!compiler->is_optimizing()); | 1704 ASSERT(!compiler->is_optimizing()); |
| 1705 __ Bind(fail); | 1705 __ Bind(fail); |
| 1706 | 1706 |
| 1707 __ lw(TMP1, FieldAddress(field_reg, Field::guarded_cid_offset())); | 1707 __ lw(CMPRES1, FieldAddress(field_reg, Field::guarded_cid_offset())); |
| 1708 __ BranchEqual(TMP1, kDynamicCid, &ok); | 1708 __ BranchEqual(CMPRES1, kDynamicCid, &ok); |
| 1709 | 1709 |
| 1710 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 1710 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
| 1711 __ sw(field_reg, Address(SP, 1 * kWordSize)); | 1711 __ sw(field_reg, Address(SP, 1 * kWordSize)); |
| 1712 __ sw(value_reg, Address(SP, 0 * kWordSize)); | 1712 __ sw(value_reg, Address(SP, 0 * kWordSize)); |
| 1713 __ CallRuntime(kUpdateFieldCidRuntimeEntry); | 1713 __ CallRuntime(kUpdateFieldCidRuntimeEntry); |
| 1714 __ Drop(2); // Drop the field and the value. | 1714 __ Drop(2); // Drop the field and the value. |
| 1715 } | 1715 } |
| 1716 | 1716 |
| 1717 __ Bind(&ok); | 1717 __ Bind(&ok); |
| 1718 } | 1718 } |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2137 __ AddImmediate(SP, FP, fp_sp_dist); | 2137 __ AddImmediate(SP, FP, fp_sp_dist); |
| 2138 | 2138 |
| 2139 ASSERT(!exception_var().is_captured()); | 2139 ASSERT(!exception_var().is_captured()); |
| 2140 ASSERT(!stacktrace_var().is_captured()); | 2140 ASSERT(!stacktrace_var().is_captured()); |
| 2141 | 2141 |
| 2142 __ sw(kExceptionObjectReg, | 2142 __ sw(kExceptionObjectReg, |
| 2143 Address(FP, exception_var().index() * kWordSize)); | 2143 Address(FP, exception_var().index() * kWordSize)); |
| 2144 __ sw(kStackTraceObjectReg, | 2144 __ sw(kStackTraceObjectReg, |
| 2145 Address(FP, stacktrace_var().index() * kWordSize)); | 2145 Address(FP, stacktrace_var().index() * kWordSize)); |
| 2146 | 2146 |
| 2147 Label next; | 2147 __ GetNextPC(CMPRES, true); |
| 2148 __ mov(TMP, RA); // Save return adress. | |
| 2149 // Restore the pool pointer. | |
| 2150 __ bal(&next); // Branch and link to next instruction to get PC in RA. | |
| 2151 __ delay_slot()->mov(CMPRES, RA); // Save PC of the following mov. | |
| 2152 | 2148 |
| 2153 // Calculate offset of pool pointer from the PC. | 2149 // Calculate offset of pool pointer from the PC. |
| 2154 const intptr_t object_pool_pc_dist = | 2150 const intptr_t object_pool_pc_dist = |
| 2155 Instructions::HeaderSize() - Instructions::object_pool_offset() + | 2151 Instructions::HeaderSize() - Instructions::object_pool_offset() + |
| 2156 compiler->assembler()->CodeSize(); | 2152 compiler->assembler()->CodeSize() - 1 * Instr::kInstrSize; |
| 2157 | 2153 |
| 2158 __ Bind(&next); | 2154 __ LoadFromOffset(PP, CMPRES, -object_pool_pc_dist); |
| 2159 __ mov(RA, TMP); // Restore return address. | |
| 2160 __ lw(PP, Address(CMPRES, -object_pool_pc_dist)); | |
| 2161 } | 2155 } |
| 2162 | 2156 |
| 2163 | 2157 |
| 2164 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary() const { | 2158 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary() const { |
| 2165 const intptr_t kNumInputs = 0; | 2159 const intptr_t kNumInputs = 0; |
| 2166 const intptr_t kNumTemps = 1; | 2160 const intptr_t kNumTemps = 1; |
| 2167 LocationSummary* summary = | 2161 LocationSummary* summary = |
| 2168 new LocationSummary(kNumInputs, | 2162 new LocationSummary(kNumInputs, |
| 2169 kNumTemps, | 2163 kNumTemps, |
| 2170 LocationSummary::kCallOnSlowPath); | 2164 LocationSummary::kCallOnSlowPath); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2208 }; | 2202 }; |
| 2209 | 2203 |
| 2210 | 2204 |
| 2211 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2205 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2212 __ TraceSimMsg("CheckStackOverflowInstr"); | 2206 __ TraceSimMsg("CheckStackOverflowInstr"); |
| 2213 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); | 2207 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); |
| 2214 compiler->AddSlowPathCode(slow_path); | 2208 compiler->AddSlowPathCode(slow_path); |
| 2215 | 2209 |
| 2216 __ LoadImmediate(TMP1, Isolate::Current()->stack_limit_address()); | 2210 __ LoadImmediate(TMP1, Isolate::Current()->stack_limit_address()); |
| 2217 | 2211 |
| 2218 __ lw(TMP1, Address(TMP1)); | 2212 __ lw(CMPRES1, Address(TMP1)); |
| 2219 __ BranchUnsignedLessEqual(SP, TMP1, slow_path->entry_label()); | 2213 __ BranchUnsignedLessEqual(SP, CMPRES1, slow_path->entry_label()); |
| 2220 if (compiler->CanOSRFunction() && in_loop()) { | 2214 if (compiler->CanOSRFunction() && in_loop()) { |
| 2221 Register temp = locs()->temp(0).reg(); | 2215 Register temp = locs()->temp(0).reg(); |
| 2222 // In unoptimized code check the usage counter to trigger OSR at loop | 2216 // In unoptimized code check the usage counter to trigger OSR at loop |
| 2223 // stack checks. Use progressively higher thresholds for more deeply | 2217 // stack checks. Use progressively higher thresholds for more deeply |
| 2224 // nested loops to attempt to hit outer loops with OSR when possible. | 2218 // nested loops to attempt to hit outer loops with OSR when possible. |
| 2225 __ LoadObject(temp, compiler->parsed_function().function()); | 2219 __ LoadObject(temp, compiler->parsed_function().function()); |
| 2226 intptr_t threshold = | 2220 intptr_t threshold = |
| 2227 FLAG_optimization_counter_threshold * (loop_depth() + 1); | 2221 FLAG_optimization_counter_threshold * (loop_depth() + 1); |
| 2228 __ lw(temp, FieldAddress(temp, Function::usage_counter_offset())); | 2222 __ lw(temp, FieldAddress(temp, Function::usage_counter_offset())); |
| 2229 __ BranchSignedGreaterEqual(temp, threshold, slow_path->entry_label()); | 2223 __ BranchSignedGreaterEqual(temp, threshold, slow_path->entry_label()); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2259 if ((value >= kCountLimit) && is_truncating) { | 2253 if ((value >= kCountLimit) && is_truncating) { |
| 2260 __ mov(result, ZR); | 2254 __ mov(result, ZR); |
| 2261 } else { | 2255 } else { |
| 2262 // Result is Mint or exception. | 2256 // Result is Mint or exception. |
| 2263 __ b(deopt); | 2257 __ b(deopt); |
| 2264 } | 2258 } |
| 2265 } else { | 2259 } else { |
| 2266 if (!is_truncating) { | 2260 if (!is_truncating) { |
| 2267 // Check for overflow (preserve left). | 2261 // Check for overflow (preserve left). |
| 2268 __ sll(TMP1, left, value); | 2262 __ sll(TMP1, left, value); |
| 2269 __ sra(TMP1, TMP1, value); | 2263 __ sra(CMPRES1, TMP1, value); |
| 2270 __ bne(TMP1, left, deopt); // Overflow. | 2264 __ bne(CMPRES1, left, deopt); // Overflow. |
| 2271 } | 2265 } |
| 2272 // Shift for result now we know there is no overflow. | 2266 // Shift for result now we know there is no overflow. |
| 2273 __ sll(result, left, value); | 2267 __ sll(result, left, value); |
| 2274 } | 2268 } |
| 2275 return; | 2269 return; |
| 2276 } | 2270 } |
| 2277 | 2271 |
| 2278 // Right (locs.in(1)) is not constant. | 2272 // Right (locs.in(1)) is not constant. |
| 2279 Register right = locs.in(1).reg(); | 2273 Register right = locs.in(1).reg(); |
| 2280 Range* right_range = shift_left->right()->definition()->range(); | 2274 Range* right_range = shift_left->right()->definition()->range(); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2327 __ sra(TMP, right, kSmiTagSize); | 2321 __ sra(TMP, right, kSmiTagSize); |
| 2328 __ sllv(result, left, TMP); | 2322 __ sllv(result, left, TMP); |
| 2329 } | 2323 } |
| 2330 } else { | 2324 } else { |
| 2331 if (right_needs_check) { | 2325 if (right_needs_check) { |
| 2332 ASSERT(shift_left->CanDeoptimize()); | 2326 ASSERT(shift_left->CanDeoptimize()); |
| 2333 __ BranchUnsignedGreaterEqual( | 2327 __ BranchUnsignedGreaterEqual( |
| 2334 right, reinterpret_cast<int32_t>(Smi::New(Smi::kBits)), deopt); | 2328 right, reinterpret_cast<int32_t>(Smi::New(Smi::kBits)), deopt); |
| 2335 } | 2329 } |
| 2336 // Left is not a constant. | 2330 // Left is not a constant. |
| 2331 Register temp = locs.temp(0).reg(); |
| 2337 // Check if count too large for handling it inlined. | 2332 // Check if count too large for handling it inlined. |
| 2338 __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP. | 2333 __ sra(temp, right, kSmiTagSize); // SmiUntag right into temp. |
| 2339 // Overflow test (preserve left, right, and TMP); | 2334 // Overflow test (preserve left, right, and temp); |
| 2340 Register temp = locs.temp(0).reg(); | 2335 __ sllv(CMPRES1, left, temp); |
| 2341 __ sllv(temp, left, TMP); | 2336 __ srav(CMPRES1, CMPRES1, temp); |
| 2342 __ srav(temp, temp, TMP); | 2337 __ bne(CMPRES1, left, deopt); // Overflow. |
| 2343 __ bne(temp, left, deopt); // Overflow. | |
| 2344 // Shift for result now we know there is no overflow. | 2338 // Shift for result now we know there is no overflow. |
| 2345 __ sllv(result, left, TMP); | 2339 __ sllv(result, left, temp); |
| 2346 } | 2340 } |
| 2347 } | 2341 } |
| 2348 | 2342 |
| 2349 | 2343 |
| 2350 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { | 2344 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { |
| 2351 const intptr_t kNumInputs = 2; | 2345 const intptr_t kNumInputs = 2; |
| 2352 const intptr_t kNumTemps = op_kind() == Token::kADD ? 1 : 0; | 2346 const intptr_t kNumTemps = op_kind() == Token::kADD ? 1 : 0; |
| 2353 LocationSummary* summary = | 2347 LocationSummary* summary = |
| 2354 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2348 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2355 if (op_kind() == Token::kTRUNCDIV) { | 2349 if (op_kind() == Token::kTRUNCDIV) { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2426 if (deopt == NULL) { | 2420 if (deopt == NULL) { |
| 2427 if (value == 2) { | 2421 if (value == 2) { |
| 2428 __ sll(result, left, 1); | 2422 __ sll(result, left, 1); |
| 2429 } else { | 2423 } else { |
| 2430 __ LoadImmediate(TMP1, value); | 2424 __ LoadImmediate(TMP1, value); |
| 2431 __ mult(left, TMP1); | 2425 __ mult(left, TMP1); |
| 2432 __ mflo(result); | 2426 __ mflo(result); |
| 2433 } | 2427 } |
| 2434 } else { | 2428 } else { |
| 2435 if (value == 2) { | 2429 if (value == 2) { |
| 2436 __ sra(TMP1, left, 31); // TMP1 = sign of left. | 2430 __ sra(CMPRES2, left, 31); // CMPRES2 = sign of left. |
| 2437 __ sll(result, left, 1); | 2431 __ sll(result, left, 1); |
| 2438 } else { | 2432 } else { |
| 2439 __ LoadImmediate(TMP1, value); | 2433 __ LoadImmediate(TMP1, value); |
| 2440 __ mult(left, TMP1); | 2434 __ mult(left, TMP1); |
| 2441 __ mflo(result); | 2435 __ mflo(result); |
| 2442 __ mfhi(TMP1); | 2436 __ mfhi(CMPRES2); |
| 2443 } | 2437 } |
| 2444 __ sra(CMPRES, result, 31); | 2438 __ sra(CMPRES, result, 31); |
| 2445 __ bne(TMP1, CMPRES, deopt); | 2439 __ bne(CMPRES1, CMPRES2, deopt); |
| 2446 } | 2440 } |
| 2447 break; | 2441 break; |
| 2448 } | 2442 } |
| 2449 case Token::kTRUNCDIV: { | 2443 case Token::kTRUNCDIV: { |
| 2450 const intptr_t value = Smi::Cast(constant).Value(); | 2444 const intptr_t value = Smi::Cast(constant).Value(); |
| 2451 if (value == 1) { | 2445 if (value == 1) { |
| 2452 if (result != left) { | 2446 if (result != left) { |
| 2453 __ mov(result, left); | 2447 __ mov(result, left); |
| 2454 } | 2448 } |
| 2455 break; | 2449 break; |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2562 __ bltz(CMPRES, deopt); | 2556 __ bltz(CMPRES, deopt); |
| 2563 } | 2557 } |
| 2564 break; | 2558 break; |
| 2565 } | 2559 } |
| 2566 case Token::kMUL: { | 2560 case Token::kMUL: { |
| 2567 __ TraceSimMsg("kMUL"); | 2561 __ TraceSimMsg("kMUL"); |
| 2568 __ sra(TMP, left, kSmiTagSize); | 2562 __ sra(TMP, left, kSmiTagSize); |
| 2569 __ mult(TMP, right); | 2563 __ mult(TMP, right); |
| 2570 __ mflo(result); | 2564 __ mflo(result); |
| 2571 if (deopt != NULL) { | 2565 if (deopt != NULL) { |
| 2572 __ mfhi(TMP1); | 2566 __ mfhi(CMPRES2); |
| 2573 __ sra(CMPRES, result, 31); | 2567 __ sra(CMPRES1, result, 31); |
| 2574 __ bne(TMP1, CMPRES, deopt); | 2568 __ bne(CMPRES1, CMPRES2, deopt); |
| 2575 } | 2569 } |
| 2576 break; | 2570 break; |
| 2577 } | 2571 } |
| 2578 case Token::kBIT_AND: { | 2572 case Token::kBIT_AND: { |
| 2579 // No overflow check. | 2573 // No overflow check. |
| 2580 __ and_(result, left, right); | 2574 __ and_(result, left, right); |
| 2581 break; | 2575 break; |
| 2582 } | 2576 } |
| 2583 case Token::kBIT_OR: { | 2577 case Token::kBIT_OR: { |
| 2584 // No overflow check. | 2578 // No overflow check. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2598 __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP. | 2592 __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP. |
| 2599 __ div(temp, TMP); | 2593 __ div(temp, TMP); |
| 2600 __ mflo(result); | 2594 __ mflo(result); |
| 2601 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 2595 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 2602 // case we cannot tag the result. | 2596 // case we cannot tag the result. |
| 2603 __ BranchEqual(result, 0x40000000, deopt); | 2597 __ BranchEqual(result, 0x40000000, deopt); |
| 2604 __ SmiTag(result); | 2598 __ SmiTag(result); |
| 2605 break; | 2599 break; |
| 2606 } | 2600 } |
| 2607 case Token::kSHR: { | 2601 case Token::kSHR: { |
| 2602 Register temp = locs()->temp(0).reg(); |
| 2608 if (CanDeoptimize()) { | 2603 if (CanDeoptimize()) { |
| 2609 __ bltz(right, deopt); | 2604 __ bltz(right, deopt); |
| 2610 } | 2605 } |
| 2611 __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP. | 2606 __ sra(temp, right, kSmiTagSize); // SmiUntag right into temp. |
| 2612 // sra operation masks the count to 5 bits. | 2607 // sra operation masks the count to 5 bits. |
| 2613 const intptr_t kCountLimit = 0x1F; | 2608 const intptr_t kCountLimit = 0x1F; |
| 2614 Range* right_range = this->right()->definition()->range(); | 2609 Range* right_range = this->right()->definition()->range(); |
| 2615 if ((right_range == NULL) || | 2610 if ((right_range == NULL) || |
| 2616 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { | 2611 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { |
| 2617 Label ok; | 2612 Label ok; |
| 2618 __ BranchSignedLessEqual(TMP, kCountLimit, &ok); | 2613 __ BranchSignedLessEqual(temp, kCountLimit, &ok); |
| 2619 __ LoadImmediate(TMP, kCountLimit); | 2614 __ LoadImmediate(temp, kCountLimit); |
| 2620 __ Bind(&ok); | 2615 __ Bind(&ok); |
| 2621 } | 2616 } |
| 2622 Register temp = locs()->temp(0).reg(); | 2617 |
| 2623 __ sra(temp, left, kSmiTagSize); // SmiUntag left into temp. | 2618 __ sra(CMPRES1, left, kSmiTagSize); // SmiUntag left into CMPRES1. |
| 2624 __ srav(result, temp, TMP); | 2619 __ srav(result, CMPRES1, temp); |
| 2625 __ SmiTag(result); | 2620 __ SmiTag(result); |
| 2626 break; | 2621 break; |
| 2627 } | 2622 } |
| 2628 case Token::kDIV: { | 2623 case Token::kDIV: { |
| 2629 // Dispatches to 'Double./'. | 2624 // Dispatches to 'Double./'. |
| 2630 // TODO(srdjan): Implement as conversion to double and double division. | 2625 // TODO(srdjan): Implement as conversion to double and double division. |
| 2631 UNREACHABLE(); | 2626 UNREACHABLE(); |
| 2632 break; | 2627 break; |
| 2633 } | 2628 } |
| 2634 case Token::kMOD: { | 2629 case Token::kMOD: { |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2769 } else if (value_cid == kSmiCid) { | 2764 } else if (value_cid == kSmiCid) { |
| 2770 __ SmiUntag(value); // Untag input before conversion. | 2765 __ SmiUntag(value); // Untag input before conversion. |
| 2771 __ mtc1(value, STMP1); | 2766 __ mtc1(value, STMP1); |
| 2772 __ cvtdw(result, STMP1); | 2767 __ cvtdw(result, STMP1); |
| 2773 } else { | 2768 } else { |
| 2774 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp); | 2769 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp); |
| 2775 Label is_smi, done; | 2770 Label is_smi, done; |
| 2776 | 2771 |
| 2777 __ andi(CMPRES, value, Immediate(kSmiTagMask)); | 2772 __ andi(CMPRES, value, Immediate(kSmiTagMask)); |
| 2778 __ beq(CMPRES, ZR, &is_smi); | 2773 __ beq(CMPRES, ZR, &is_smi); |
| 2779 __ LoadClassId(TMP, value); | 2774 __ LoadClassId(CMPRES1, value); |
| 2780 __ BranchNotEqual(TMP, kDoubleCid, deopt); | 2775 __ BranchNotEqual(CMPRES1, kDoubleCid, deopt); |
| 2781 __ LoadDFromOffset(result, value, Double::value_offset() - kHeapObjectTag); | 2776 __ LoadDFromOffset(result, value, Double::value_offset() - kHeapObjectTag); |
| 2782 __ b(&done); | 2777 __ b(&done); |
| 2783 __ Bind(&is_smi); | 2778 __ Bind(&is_smi); |
| 2784 // TODO(regis): Why do we preserve value here but not above? | 2779 // TODO(regis): Why do we preserve value here but not above? |
| 2785 __ sra(TMP, value, 1); | 2780 __ sra(TMP, value, 1); |
| 2786 __ mtc1(TMP, STMP1); | 2781 __ mtc1(TMP, STMP1); |
| 2787 __ cvtdw(result, STMP1); | 2782 __ cvtdw(result, STMP1); |
| 2788 __ Bind(&done); | 2783 __ Bind(&done); |
| 2789 } | 2784 } |
| 2790 } | 2785 } |
| (...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3462 summary->set_in(0, Location::RequiresRegister()); | 3457 summary->set_in(0, Location::RequiresRegister()); |
| 3463 return summary; | 3458 return summary; |
| 3464 } | 3459 } |
| 3465 | 3460 |
| 3466 | 3461 |
| 3467 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3462 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3468 __ TraceSimMsg("CheckSmiInstr"); | 3463 __ TraceSimMsg("CheckSmiInstr"); |
| 3469 Register value = locs()->in(0).reg(); | 3464 Register value = locs()->in(0).reg(); |
| 3470 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 3465 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 3471 kDeoptCheckSmi); | 3466 kDeoptCheckSmi); |
| 3472 __ andi(TMP1, value, Immediate(kSmiTagMask)); | 3467 __ andi(CMPRES1, value, Immediate(kSmiTagMask)); |
| 3473 __ bne(TMP1, ZR, deopt); | 3468 __ bne(CMPRES1, ZR, deopt); |
| 3474 } | 3469 } |
| 3475 | 3470 |
| 3476 | 3471 |
| 3477 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary() const { | 3472 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary() const { |
| 3478 const intptr_t kNumInputs = 2; | 3473 const intptr_t kNumInputs = 2; |
| 3479 const intptr_t kNumTemps = 0; | 3474 const intptr_t kNumTemps = 0; |
| 3480 LocationSummary* locs = | 3475 LocationSummary* locs = |
| 3481 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3476 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3482 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); | 3477 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); |
| 3483 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); | 3478 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3730 } else { | 3725 } else { |
| 3731 compiler->EmitEqualityRegRegCompare(left.reg(), | 3726 compiler->EmitEqualityRegRegCompare(left.reg(), |
| 3732 right.reg(), | 3727 right.reg(), |
| 3733 needs_number_check(), | 3728 needs_number_check(), |
| 3734 token_pos()); | 3729 token_pos()); |
| 3735 } | 3730 } |
| 3736 | 3731 |
| 3737 Register result = locs()->out().reg(); | 3732 Register result = locs()->out().reg(); |
| 3738 Label load_true, done; | 3733 Label load_true, done; |
| 3739 if (kind() == Token::kEQ_STRICT) { | 3734 if (kind() == Token::kEQ_STRICT) { |
| 3740 __ beq(CMPRES, TMP1, &load_true); | 3735 __ beq(CMPRES1, CMPRES2, &load_true); |
| 3741 } else { | 3736 } else { |
| 3742 ASSERT(kind() == Token::kNE_STRICT); | 3737 ASSERT(kind() == Token::kNE_STRICT); |
| 3743 __ bne(CMPRES, TMP1, &load_true); | 3738 __ bne(CMPRES1, CMPRES2, &load_true); |
| 3744 } | 3739 } |
| 3745 __ LoadObject(result, Bool::False()); | 3740 __ LoadObject(result, Bool::False()); |
| 3746 __ b(&done); | 3741 __ b(&done); |
| 3747 __ Bind(&load_true); | 3742 __ Bind(&load_true); |
| 3748 __ LoadObject(result, Bool::True()); | 3743 __ LoadObject(result, Bool::True()); |
| 3749 __ Bind(&done); | 3744 __ Bind(&done); |
| 3750 } | 3745 } |
| 3751 | 3746 |
| 3752 | 3747 |
| 3753 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 3748 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3864 compiler->GenerateCall(token_pos(), | 3859 compiler->GenerateCall(token_pos(), |
| 3865 &label, | 3860 &label, |
| 3866 PcDescriptors::kOther, | 3861 PcDescriptors::kOther, |
| 3867 locs()); | 3862 locs()); |
| 3868 __ Drop(2); // Discard type arguments and receiver. | 3863 __ Drop(2); // Discard type arguments and receiver. |
| 3869 } | 3864 } |
| 3870 | 3865 |
| 3871 } // namespace dart | 3866 } // namespace dart |
| 3872 | 3867 |
| 3873 #endif // defined TARGET_ARCH_MIPS | 3868 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |