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

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

Issue 27307005: Change == into an instance call to allow polymorphic inlining of ==. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: rebased, addressed comments Created 7 years, 1 month 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
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | runtime/vm/intermediate_language_x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 297 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
298 locs->set_in(0, Location::RegisterOrConstant(left())); 298 locs->set_in(0, Location::RegisterOrConstant(left()));
299 // Only one input can be a constant operand. The case of two constant 299 // Only one input can be a constant operand. The case of two constant
300 // operands should be handled by constant propagation. 300 // operands should be handled by constant propagation.
301 locs->set_in(1, locs->in(0).IsConstant() 301 locs->set_in(1, locs->in(0).IsConstant()
302 ? Location::RequiresRegister() 302 ? Location::RequiresRegister()
303 : Location::RegisterOrConstant(right())); 303 : Location::RegisterOrConstant(right()));
304 locs->set_out(Location::RequiresRegister()); 304 locs->set_out(Location::RequiresRegister());
305 return locs; 305 return locs;
306 } 306 }
307 if (IsCheckedStrictEqual()) { 307 UNREACHABLE();
308 const intptr_t kNumTemps = 1; 308 return NULL;
309 LocationSummary* locs =
310 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
311 locs->set_in(0, Location::RequiresRegister());
312 locs->set_in(1, Location::RequiresRegister());
313 locs->set_temp(0, Location::RequiresRegister());
314 locs->set_out(Location::RequiresRegister());
315 return locs;
316 }
317 if (IsPolymorphic()) {
318 const intptr_t kNumTemps = 1;
319 LocationSummary* locs =
320 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
321 locs->set_in(0, Location::RegisterLocation(A1));
322 locs->set_in(1, Location::RegisterLocation(A0));
323 locs->set_temp(0, Location::RegisterLocation(T0));
324 locs->set_out(Location::RegisterLocation(V0));
325 return locs;
326 }
327 const intptr_t kNumTemps = 1;
328 LocationSummary* locs =
329 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
330 locs->set_in(0, Location::RegisterLocation(A1));
331 locs->set_in(1, Location::RegisterLocation(A0));
332 locs->set_temp(0, Location::RegisterLocation(T0));
333 locs->set_out(Location::RegisterLocation(V0));
334 return locs;
335 }
336
337
338 // A1: left.
339 // A0: right.
340 // Uses T0 to load ic_call_data.
341 // Result in V0.
342 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler,
343 intptr_t deopt_id,
344 intptr_t token_pos,
345 Token::Kind kind,
346 LocationSummary* locs,
347 const ICData& original_ic_data) {
348 if (!compiler->is_optimizing()) {
349 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
350 deopt_id,
351 token_pos);
352 }
353 const int kNumberOfArguments = 2;
354 const Array& kNoArgumentNames = Object::null_array();
355 const int kNumArgumentsChecked = 2;
356
357 __ TraceSimMsg("EmitEqualityAsInstanceCall");
358 __ Comment("EmitEqualityAsInstanceCall");
359
360 ICData& equality_ic_data = ICData::ZoneHandle();
361 if (compiler->is_optimizing() && FLAG_propagate_ic_data) {
362 ASSERT(!original_ic_data.IsNull());
363 if (original_ic_data.NumberOfChecks() == 0) {
364 // IC call for reoptimization populates original ICData.
365 equality_ic_data = original_ic_data.raw();
366 } else {
367 // Megamorphic call.
368 equality_ic_data = original_ic_data.AsUnaryClassChecks();
369 }
370 } else {
371 const Array& arguments_descriptor =
372 Array::Handle(ArgumentsDescriptor::New(kNumberOfArguments,
373 kNoArgumentNames));
374 equality_ic_data = ICData::New(compiler->parsed_function().function(),
375 Symbols::EqualOperator(),
376 arguments_descriptor,
377 deopt_id,
378 kNumArgumentsChecked);
379 }
380 compiler->GenerateInstanceCall(deopt_id,
381 token_pos,
382 kNumberOfArguments,
383 kNoArgumentNames,
384 locs,
385 equality_ic_data);
386 if (kind == Token::kNE) {
387 Label true_label, done;
388 // Negate the condition: true label returns false and vice versa.
389 __ BranchEqual(V0, Bool::True(), &true_label);
390 __ LoadObject(V0, Bool::True());
391 __ b(&done);
392 __ Bind(&true_label);
393 __ LoadObject(V0, Bool::False());
394 __ Bind(&done);
395 }
396 } 309 }
397 310
398 311
399 static void LoadValueCid(FlowGraphCompiler* compiler, 312 static void LoadValueCid(FlowGraphCompiler* compiler,
400 Register value_cid_reg, 313 Register value_cid_reg,
401 Register value_reg, 314 Register value_reg,
402 Label* value_is_smi = NULL) { 315 Label* value_is_smi = NULL) {
403 __ TraceSimMsg("LoadValueCid"); 316 __ TraceSimMsg("LoadValueCid");
404 Label done; 317 Label done;
405 if (value_is_smi == NULL) { 318 if (value_is_smi == NULL) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 case GE: __ beq(CMPRES1, ZR, is_true); break; 354 case GE: __ beq(CMPRES1, ZR, is_true); break;
442 case LT: __ bne(CMPRES1, ZR, is_true); break; 355 case LT: __ bne(CMPRES1, ZR, is_true); break;
443 case LE: __ beq(CMPRES2, ZR, is_true); break; 356 case LE: __ beq(CMPRES2, ZR, is_true); break;
444 default: 357 default:
445 UNREACHABLE(); 358 UNREACHABLE();
446 break; 359 break;
447 } 360 }
448 } 361 }
449 362
450 363
451 // A1: left, also on stack.
452 // A0: right, also on stack.
453 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler,
454 const ICData& orig_ic_data,
455 LocationSummary* locs,
456 BranchInstr* branch,
457 Token::Kind kind,
458 intptr_t deopt_id,
459 intptr_t token_pos) {
460 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
461 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks());
462 ASSERT(ic_data.NumberOfChecks() > 0);
463 ASSERT(ic_data.num_args_tested() == 1);
464 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality);
465 Register left = locs->in(0).reg();
466 Register right = locs->in(1).reg();
467 ASSERT(left == A1);
468 ASSERT(right == A0);
469 Register temp = locs->temp(0).reg();
470
471 __ TraceSimMsg("EmitEqualityAsPolymorphicCall");
472 __ Comment("EmitEqualityAsPolymorphicCall");
473
474 LoadValueCid(compiler, temp, left,
475 (ic_data.GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt);
476 // 'temp' contains class-id of the left argument.
477 ObjectStore* object_store = Isolate::Current()->object_store();
478 Condition cond = TokenKindToSmiCondition(kind);
479 Label done;
480 const intptr_t len = ic_data.NumberOfChecks();
481 for (intptr_t i = 0; i < len; i++) {
482 // Assert that the Smi is at position 0, if at all.
483 ASSERT((ic_data.GetReceiverClassIdAt(i) != kSmiCid) || (i == 0));
484 Label next_test;
485 if (i < len - 1) {
486 __ BranchNotEqual(temp, ic_data.GetReceiverClassIdAt(i), &next_test);
487 } else {
488 __ BranchNotEqual(temp, ic_data.GetReceiverClassIdAt(i), deopt);
489 }
490 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i));
491 if (target.Owner() == object_store->object_class()) {
492 // Object.== is same as ===.
493 __ Drop(2);
494 __ slt(CMPRES1, left, right);
495 __ slt(CMPRES2, right, left);
496 if (branch != NULL) {
497 branch->EmitBranchOnCondition(compiler, cond);
498 } else {
499 Register result = locs->out().reg();
500 Label load_true;
501 EmitBranchAfterCompare(compiler, cond, &load_true);
502 __ LoadObject(result, Bool::False());
503 __ b(&done);
504 __ Bind(&load_true);
505 __ LoadObject(result, Bool::True());
506 }
507 } else {
508 const int kNumberOfArguments = 2;
509 const Array& kNoArgumentNames = Object::null_array();
510 compiler->GenerateStaticCall(deopt_id,
511 token_pos,
512 target,
513 kNumberOfArguments,
514 kNoArgumentNames,
515 locs);
516 if (branch == NULL) {
517 if (kind == Token::kNE) {
518 Label is_true;
519 __ CompareObject(CMPRES1, CMPRES2, V0, Bool::True());
520 __ beq(CMPRES, CMPRES2, &is_true);
521 __ LoadObject(V0, Bool::True());
522 __ b(&done);
523 __ Bind(&is_true);
524 __ LoadObject(V0, Bool::False());
525 }
526 } else {
527 if (branch->is_checked()) {
528 EmitAssertBoolean(V0, token_pos, deopt_id, locs, compiler);
529 }
530 __ CompareObject(CMPRES1, CMPRES2, V0, Bool::True());
531 branch->EmitBranchOnCondition(compiler, cond);
532 }
533 }
534 if (i < len - 1) {
535 __ b(&done);
536 __ Bind(&next_test);
537 }
538 }
539 __ Bind(&done);
540 }
541
542
543 // Emit code when ICData's targets are all Object == (which is ===).
544 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler,
545 const ICData& orig_ic_data,
546 const LocationSummary& locs,
547 Token::Kind kind,
548 BranchInstr* branch,
549 intptr_t deopt_id) {
550 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
551 Register left = locs.in(0).reg();
552 Register right = locs.in(1).reg();
553 Register temp = locs.temp(0).reg();
554 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality);
555
556 __ Comment("CheckedStrictEqual");
557
558 __ andi(CMPRES, left, Immediate(kSmiTagMask));
559 __ beq(CMPRES, ZR, deopt);
560 // 'left' is not Smi.
561 Label identity_compare;
562 __ LoadImmediate(CMPRES1, reinterpret_cast<int32_t>(Object::null()));
563 __ beq(right, CMPRES1, &identity_compare);
564 __ beq(left, CMPRES1, &identity_compare);
565
566 __ LoadClassId(temp, left);
567 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks());
568 const intptr_t len = ic_data.NumberOfChecks();
569 for (intptr_t i = 0; i < len; i++) {
570 if (i == (len - 1)) {
571 __ BranchNotEqual(temp, ic_data.GetReceiverClassIdAt(i), deopt);
572 } else {
573 __ BranchEqual(temp, ic_data.GetReceiverClassIdAt(i), &identity_compare);
574 }
575 }
576 __ Bind(&identity_compare);
577 __ subu(CMPRES1, left, right);
578 if (branch == NULL) {
579 Label done, is_equal;
580 Register result = locs.out().reg();
581 __ beq(CMPRES, ZR, &is_equal);
582 // Not equal.
583 __ LoadObject(result, Bool::Get(kind != Token::kEQ));
584 __ b(&done);
585 __ Bind(&is_equal);
586 __ LoadObject(result, Bool::Get(kind == Token::kEQ));
587 __ Bind(&done);
588
589 } else {
590 Condition cond = TokenKindToSmiCondition(kind);
591 __ mov(CMPRES2, ZR);
592 branch->EmitBranchOnCondition(compiler, cond);
593 }
594 }
595
596
597 // First test if receiver is NULL, in which case === is applied.
598 // If type feedback was provided (lists of <class-id, target>), do a
599 // type by type check (either === or static call to the operator.
600 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler,
601 LocationSummary* locs,
602 Token::Kind kind,
603 BranchInstr* branch,
604 const ICData& ic_data,
605 intptr_t deopt_id,
606 intptr_t token_pos) {
607 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
608 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0));
609 Register left = locs->in(0).reg();
610 Register right = locs->in(1).reg();
611 __ TraceSimMsg("EmitGenericEqualityCompare");
612 __ Comment("EmitGenericEqualityCompare");
613 ASSERT(left == A1);
614 ASSERT(right == A0);
615 __ addiu(SP, SP, Immediate(-2 * kWordSize));
616 __ sw(A1, Address(SP, 1 * kWordSize));
617 __ sw(A0, Address(SP, 0 * kWordSize));
618 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind,
619 deopt_id, token_pos);
620 }
621
622
623 static Condition FlipCondition(Condition condition) { 364 static Condition FlipCondition(Condition condition) {
624 switch (condition) { 365 switch (condition) {
625 case EQ: return EQ; 366 case EQ: return EQ;
626 case NE: return NE; 367 case NE: return NE;
627 case LT: return GT; 368 case LT: return GT;
628 case LE: return GE; 369 case LE: return GE;
629 case GT: return LT; 370 case GT: return LT;
630 case GE: return LE; 371 case GE: return LE;
631 default: 372 default:
632 UNREACHABLE(); 373 UNREACHABLE();
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
732 return; 473 return;
733 } 474 }
734 if (operation_cid() == kMintCid) { 475 if (operation_cid() == kMintCid) {
735 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), kNoBranch); 476 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), kNoBranch);
736 return; 477 return;
737 } 478 }
738 if (operation_cid() == kDoubleCid) { 479 if (operation_cid() == kDoubleCid) {
739 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch); 480 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch);
740 return; 481 return;
741 } 482 }
742 if (IsCheckedStrictEqual()) { 483 UNREACHABLE();
743 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch,
744 deopt_id());
745 return;
746 }
747 if (IsPolymorphic()) {
748 EmitGenericEqualityCompare(compiler, locs(), kind(), kNoBranch, *ic_data(),
749 deopt_id(), token_pos());
750 return;
751 }
752 Register left = locs()->in(0).reg();
753 Register right = locs()->in(1).reg();
754 ASSERT(left == A1);
755 ASSERT(right == A0);
756 __ addiu(SP, SP, Immediate(-2 * kWordSize));
757 __ sw(A1, Address(SP, 1 * kWordSize));
758 __ sw(A0, Address(SP, 0 * kWordSize));
759 EmitEqualityAsInstanceCall(compiler,
760 deopt_id(),
761 token_pos(),
762 kind(),
763 locs(),
764 *ic_data());
765 ASSERT(locs()->out().reg() == V0);
766 } 484 }
767 485
768 486
769 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, 487 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
770 BranchInstr* branch) { 488 BranchInstr* branch) {
771 __ TraceSimMsg("EqualityCompareInstr"); 489 __ TraceSimMsg("EqualityCompareInstr");
772 __ Comment("EqualityCompareInstr:BranchCode"); 490 __ Comment("EqualityCompareInstr:BranchCode");
773 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); 491 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
774 if (operation_cid() == kSmiCid) { 492 if (operation_cid() == kSmiCid) {
775 // Deoptimizes if both arguments not Smi. 493 // Deoptimizes if both arguments not Smi.
776 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); 494 EmitSmiComparisonOp(compiler, *locs(), kind(), branch);
777 return; 495 return;
778 } 496 }
779 if (operation_cid() == kMintCid) { 497 if (operation_cid() == kMintCid) {
780 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), branch); 498 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), branch);
781 return; 499 return;
782 } 500 }
783 if (operation_cid() == kDoubleCid) { 501 if (operation_cid() == kDoubleCid) {
784 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); 502 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
785 return; 503 return;
786 } 504 }
787 if (IsCheckedStrictEqual()) { 505 UNREACHABLE();
788 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch,
789 deopt_id());
790 return;
791 }
792 if (IsPolymorphic()) {
793 EmitGenericEqualityCompare(compiler, locs(), kind(), branch, *ic_data(),
794 deopt_id(), token_pos());
795 return;
796 }
797 Register left = locs()->in(0).reg();
798 Register right = locs()->in(1).reg();
799 ASSERT(left == A1);
800 ASSERT(right == A0);
801 __ addiu(SP, SP, Immediate(-2 * kWordSize));
802 __ sw(A1, Address(SP, 1 * kWordSize));
803 __ sw(A0, Address(SP, 0 * kWordSize));
804 EmitEqualityAsInstanceCall(compiler,
805 deopt_id(),
806 token_pos(),
807 Token::kEQ, // kNE reverse occurs at branch.
808 locs(),
809 *ic_data());
810 if (branch->is_checked()) {
811 EmitAssertBoolean(V0, token_pos(), deopt_id(), locs(), compiler);
812 }
813 Condition branch_condition = (kind() == Token::kNE) ? NE : EQ;
814 __ CompareObject(CMPRES1, CMPRES2, V0, Bool::True());
815 branch->EmitBranchOnCondition(compiler, branch_condition);
816 } 506 }
817 507
818 508
819 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { 509 LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
820 const intptr_t kNumInputs = 2; 510 const intptr_t kNumInputs = 2;
821 const intptr_t kNumTemps = 0; 511 const intptr_t kNumTemps = 0;
822 if (operation_cid() == kMintCid) { 512 if (operation_cid() == kMintCid) {
823 const intptr_t kNumTemps = 2; 513 const intptr_t kNumTemps = 2;
824 LocationSummary* locs = 514 LocationSummary* locs =
825 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 515 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
(...skipping 3264 matching lines...) Expand 10 before | Expand all | Expand 10 after
4090 compiler->GenerateCall(token_pos(), 3780 compiler->GenerateCall(token_pos(),
4091 &label, 3781 &label,
4092 PcDescriptors::kOther, 3782 PcDescriptors::kOther,
4093 locs()); 3783 locs());
4094 __ Drop(2); // Discard type arguments and receiver. 3784 __ Drop(2); // Discard type arguments and receiver.
4095 } 3785 }
4096 3786
4097 } // namespace dart 3787 } // namespace dart
4098 3788
4099 #endif // defined TARGET_ARCH_MIPS 3789 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | runtime/vm/intermediate_language_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698