Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(110)

Side by Side Diff: runtime/vm/intermediate_language_mips.cc

Issue 20369003: Implements far branch targets for MIPS. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698