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

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

Issue 15934025: Enables more VM tests for SIMMIPS. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 6 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
« no previous file with comments | « runtime/vm/intermediate_language_arm.cc ('k') | runtime/vm/intrinsifier_arm.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 "lib/error.h" 10 #include "lib/error.h"
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 Register obj = locs()->in(0).reg(); 261 Register obj = locs()->in(0).reg();
262 Register result = locs()->out().reg(); 262 Register result = locs()->out().reg();
263 263
264 __ TraceSimMsg("AssertBooleanInstr"); 264 __ TraceSimMsg("AssertBooleanInstr");
265 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); 265 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler);
266 ASSERT(obj == result); 266 ASSERT(obj == result);
267 } 267 }
268 268
269 269
270 LocationSummary* ArgumentDefinitionTestInstr::MakeLocationSummary() const { 270 LocationSummary* ArgumentDefinitionTestInstr::MakeLocationSummary() const {
271 UNIMPLEMENTED(); 271 const intptr_t kNumInputs = 1;
272 return NULL; 272 const intptr_t kNumTemps = 0;
273 LocationSummary* locs =
274 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
275 locs->set_in(0, Location::RegisterLocation(T0));
276 locs->set_out(Location::RegisterLocation(T0));
277 return locs;
273 } 278 }
274 279
275 280
276 void ArgumentDefinitionTestInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 281 void ArgumentDefinitionTestInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
277 UNIMPLEMENTED(); 282 Register saved_args_desc = locs()->in(0).reg();
283 Register result = locs()->out().reg();
284
285 __ TraceSimMsg("ArgumentDefinitionTestInstr");
286
287 __ addiu(SP, SP, Immediate(-4 * kWordSize));
288 // Push the result place holder initialized to NULL.
289 __ LoadObject(TMP1, Object::ZoneHandle());
290 __ sw(TMP1, Address(SP, 3 * kWordSize));
291 __ LoadImmediate(TMP1, Smi::RawValue(formal_parameter_index()));
292 __ sw(TMP1, Address(SP, 2 * kWordSize));
293 __ LoadObject(TMP1, formal_parameter_name());
294 __ sw(TMP1, Address(SP, 1 * kWordSize));
295 __ sw(saved_args_desc, Address(SP, 0 * kWordSize));
296 compiler->GenerateCallRuntime(token_pos(),
297 deopt_id(),
298 kArgumentDefinitionTestRuntimeEntry,
299 locs());
300 __ lw(result, Address(SP, 3 * kWordSize)); // Pop bool result.
301 __ addiu(SP, SP, Immediate(4 * kWordSize));
278 } 302 }
279 303
280 304
281 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const { 305 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
282 const intptr_t kNumInputs = 2; 306 const intptr_t kNumInputs = 2;
283 const bool is_checked_strict_equal = 307 const bool is_checked_strict_equal =
284 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); 308 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
285 if (receiver_class_id() == kMintCid) { 309 if (receiver_class_id() == kMintCid) {
286 const intptr_t kNumTemps = 1; 310 const intptr_t kNumTemps = 1;
287 LocationSummary* locs = 311 LocationSummary* locs =
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 // A1: left. 372 // A1: left.
349 // A0: right. 373 // A0: right.
350 // Uses T0 to load ic_call_data. 374 // Uses T0 to load ic_call_data.
351 // Result in V0. 375 // Result in V0.
352 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, 376 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler,
353 intptr_t deopt_id, 377 intptr_t deopt_id,
354 intptr_t token_pos, 378 intptr_t token_pos,
355 Token::Kind kind, 379 Token::Kind kind,
356 LocationSummary* locs, 380 LocationSummary* locs,
357 const ICData& original_ic_data) { 381 const ICData& original_ic_data) {
358 __ TraceSimMsg("EmitEqualityAsInstanceCall");
359 if (!compiler->is_optimizing()) { 382 if (!compiler->is_optimizing()) {
360 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 383 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
361 deopt_id, 384 deopt_id,
362 token_pos); 385 token_pos);
363 } 386 }
364 const int kNumberOfArguments = 2; 387 const int kNumberOfArguments = 2;
365 const Array& kNoArgumentNames = Array::Handle(); 388 const Array& kNoArgumentNames = Array::Handle();
366 const int kNumArgumentsChecked = 2; 389 const int kNumArgumentsChecked = 2;
367 390
391 __ TraceSimMsg("EmitEqualityAsInstanceCall");
368 Label check_identity; 392 Label check_identity;
393 __ lw(A1, Address(SP, 1 * kWordSize));
394 __ lw(A0, Address(SP, 0 * kWordSize));
369 __ beq(A1, NULLREG, &check_identity); 395 __ beq(A1, NULLREG, &check_identity);
370 __ beq(A0, NULLREG, &check_identity); 396 __ beq(A0, NULLREG, &check_identity);
371 397
372 ICData& equality_ic_data = ICData::ZoneHandle(); 398 ICData& equality_ic_data = ICData::ZoneHandle();
373 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { 399 if (compiler->is_optimizing() && FLAG_propagate_ic_data) {
374 ASSERT(!original_ic_data.IsNull()); 400 ASSERT(!original_ic_data.IsNull());
375 if (original_ic_data.NumberOfChecks() == 0) { 401 if (original_ic_data.NumberOfChecks() == 0) {
376 // IC call for reoptimization populates original ICData. 402 // IC call for reoptimization populates original ICData.
377 equality_ic_data = original_ic_data.raw(); 403 equality_ic_data = original_ic_data.raw();
378 } else { 404 } else {
379 // Megamorphic call. 405 // Megamorphic call.
380 equality_ic_data = original_ic_data.AsUnaryClassChecks(); 406 equality_ic_data = original_ic_data.AsUnaryClassChecks();
381 } 407 }
382 } else { 408 } else {
383 equality_ic_data = ICData::New(compiler->parsed_function().function(), 409 equality_ic_data = ICData::New(compiler->parsed_function().function(),
384 Symbols::EqualOperator(), 410 Symbols::EqualOperator(),
385 deopt_id, 411 deopt_id,
386 kNumArgumentsChecked); 412 kNumArgumentsChecked);
387 } 413 }
388 __ addiu(SP, SP, Immediate(-2 * kWordSize));
389 __ sw(A1, Address(SP, 1 * kWordSize));
390 __ sw(A0, Address(SP, 0 * kWordSize));
391 compiler->GenerateInstanceCall(deopt_id, 414 compiler->GenerateInstanceCall(deopt_id,
392 token_pos, 415 token_pos,
393 kNumberOfArguments, 416 kNumberOfArguments,
394 kNoArgumentNames, 417 kNoArgumentNames,
395 locs, 418 locs,
396 equality_ic_data); 419 equality_ic_data);
397 Label check_ne; 420 Label check_ne;
398 __ b(&check_ne); 421 __ b(&check_ne);
399 422
400 __ Bind(&check_identity); 423 __ Bind(&check_identity);
401 Label equality_done; 424 Label equality_done;
402 if (compiler->is_optimizing()) { 425 if (compiler->is_optimizing()) {
403 // No need to update IC data. 426 // No need to update IC data.
404 Label is_true; 427 Label is_true;
428 __ lw(A1, Address(SP, 1 * kWordSize));
429 __ lw(A0, Address(SP, 0 * kWordSize));
430 __ addiu(SP, SP, Immediate(2 * kWordSize));
405 __ beq(A1, A0, &is_true); 431 __ beq(A1, A0, &is_true);
406 __ LoadObject(V0, (kind == Token::kEQ) ? Bool::False() : Bool::True()); 432 __ LoadObject(V0, (kind == Token::kEQ) ? Bool::False() : Bool::True());
407 __ b(&equality_done); 433 __ b(&equality_done);
408 __ Bind(&is_true); 434 __ Bind(&is_true);
409 __ LoadObject(V0, (kind == Token::kEQ) ? Bool::True() : Bool::False()); 435 __ LoadObject(V0, (kind == Token::kEQ) ? Bool::True() : Bool::False());
410 if (kind == Token::kNE) { 436 if (kind == Token::kNE) {
411 // Skip not-equal result conversion. 437 // Skip not-equal result conversion.
412 __ b(&equality_done); 438 __ b(&equality_done);
413 } 439 }
414 } else { 440 } else {
415 // Call stub, load IC data in register. The stub will update ICData if 441 // Call stub, load IC data in register. The stub will update ICData if
416 // necessary. 442 // necessary.
417 Register ic_data_reg = locs->temp(0).reg(); 443 Register ic_data_reg = locs->temp(0).reg();
418 ASSERT(ic_data_reg == T0); // Stub depends on it. 444 ASSERT(ic_data_reg == T0); // Stub depends on it.
419 __ LoadObject(ic_data_reg, equality_ic_data); 445 __ LoadObject(ic_data_reg, equality_ic_data);
420 // Pass left in A1 and right in A0. 446 // Pass left in A1 and right in A0.
421 compiler->GenerateCall(token_pos, 447 compiler->GenerateCall(token_pos,
422 &StubCode::EqualityWithNullArgLabel(), 448 &StubCode::EqualityWithNullArgLabel(),
423 PcDescriptors::kRuntimeCall, 449 PcDescriptors::kRuntimeCall,
424 locs); 450 locs);
451 __ Drop(2);
425 } 452 }
426 __ Bind(&check_ne); 453 __ Bind(&check_ne);
427 if (kind == Token::kNE) { 454 if (kind == Token::kNE) {
428 Label true_label, done; 455 Label true_label, done;
429 // Negate the condition: true label returns false and vice versa. 456 // Negate the condition: true label returns false and vice versa.
430 __ BranchEqual(V0, Bool::True(), &true_label); 457 __ BranchEqual(V0, Bool::True(), &true_label);
431 __ LoadObject(V0, Bool::True()); 458 __ LoadObject(V0, Bool::True());
432 __ b(&done); 459 __ b(&done);
433 __ Bind(&true_label); 460 __ Bind(&true_label);
434 __ LoadObject(V0, Bool::False()); 461 __ LoadObject(V0, Bool::False());
(...skipping 16 matching lines...) Expand all
451 if (value_is_smi == NULL) { 478 if (value_is_smi == NULL) {
452 __ beq(TMP1, ZR, &done); 479 __ beq(TMP1, ZR, &done);
453 } else { 480 } else {
454 __ beq(TMP1, ZR, value_is_smi); 481 __ beq(TMP1, ZR, value_is_smi);
455 } 482 }
456 __ LoadClassId(value_cid_reg, value_reg); 483 __ LoadClassId(value_cid_reg, value_reg);
457 __ Bind(&done); 484 __ Bind(&done);
458 } 485 }
459 486
460 487
488 static Condition TokenKindToSmiCondition(Token::Kind kind) {
489 switch (kind) {
490 case Token::kEQ: return EQ;
491 case Token::kNE: return NE;
492 case Token::kLT: return LT;
493 case Token::kGT: return GT;
494 case Token::kLTE: return LE;
495 case Token::kGTE: return GE;
496 default:
497 UNREACHABLE();
498 return VS;
499 }
500 }
501
502
503 // Branches on condition c assuming comparison results in CMPRES and TMP1.
504 static void EmitBranchAfterCompare(
505 FlowGraphCompiler* compiler, Condition c, Label* is_true) {
506 switch (c) {
507 case EQ: __ beq(CMPRES, TMP1, is_true); break;
508 case NE: __ bne(CMPRES, TMP1, is_true); break;
509 case GT: __ bne(TMP1, ZR, is_true); break;
510 case GE: __ beq(CMPRES, ZR, is_true); break;
511 case LT: __ bne(CMPRES, ZR, is_true); break;
512 case LE: __ beq(TMP1, ZR, is_true); break;
513 default:
514 UNREACHABLE();
515 break;
516 }
517 }
518
519
520 // A1: left, also on stack.
521 // A0: right, also on stack.
522 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler,
523 const ICData& orig_ic_data,
524 LocationSummary* locs,
525 BranchInstr* branch,
526 Token::Kind kind,
527 intptr_t deopt_id,
528 intptr_t token_pos) {
529 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
530 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks());
531 ASSERT(ic_data.NumberOfChecks() > 0);
532 ASSERT(ic_data.num_args_tested() == 1);
533 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality);
534 Register left = locs->in(0).reg();
535 Register right = locs->in(1).reg();
536 ASSERT(left == A1);
537 ASSERT(right == A0);
538 Register temp = locs->temp(0).reg();
539
540 __ TraceSimMsg("EmitEqualityAsPolymorphicCall");
541
542 LoadValueCid(compiler, temp, left,
543 (ic_data.GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt);
544 // 'temp' contains class-id of the left argument.
545 ObjectStore* object_store = Isolate::Current()->object_store();
546 Condition cond = TokenKindToSmiCondition(kind);
547 Label done;
548 const intptr_t len = ic_data.NumberOfChecks();
549 for (intptr_t i = 0; i < len; i++) {
550 // Assert that the Smi is at position 0, if at all.
551 ASSERT((ic_data.GetReceiverClassIdAt(i) != kSmiCid) || (i == 0));
552 Label next_test;
553 if (i < len - 1) {
554 __ BranchNotEqual(temp, ic_data.GetReceiverClassIdAt(i), &next_test);
555 } else {
556 __ BranchNotEqual(temp, ic_data.GetReceiverClassIdAt(i), deopt);
557 }
558 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i));
559 if (target.Owner() == object_store->object_class()) {
560 // Object.== is same as ===.
561 __ Drop(2);
562 __ slt(CMPRES, left, right);
563 __ slt(TMP1, right, left);
564 if (branch != NULL) {
565 branch->EmitBranchOnCondition(compiler, cond);
566 } else {
567 Register result = locs->out().reg();
568 Label load_true;
569 EmitBranchAfterCompare(compiler, cond, &load_true);
570 __ LoadObject(result, Bool::False());
571 __ b(&done);
572 __ Bind(&load_true);
573 __ LoadObject(result, Bool::True());
574 }
575 } else {
576 const int kNumberOfArguments = 2;
577 const Array& kNoArgumentNames = Array::Handle();
578 compiler->GenerateStaticCall(deopt_id,
579 token_pos,
580 target,
581 kNumberOfArguments,
582 kNoArgumentNames,
583 locs);
584 if (branch == NULL) {
585 if (kind == Token::kNE) {
586 Label is_true;
587 __ CompareObject(CMPRES, TMP1, V0, Bool::True());
588 __ beq(CMPRES, TMP1, &is_true);
589 __ LoadObject(V0, Bool::True());
590 __ b(&done);
591 __ Bind(&is_true);
592 __ LoadObject(V0, Bool::False());
593 }
594 } else {
595 if (branch->is_checked()) {
596 EmitAssertBoolean(V0, token_pos, deopt_id, locs, compiler);
597 }
598 __ CompareObject(CMPRES, TMP1, V0, Bool::True());
599 branch->EmitBranchOnCondition(compiler, cond);
600 }
601 }
602 if (i < len - 1) {
603 __ b(&done);
604 __ Bind(&next_test);
605 }
606 }
607 __ Bind(&done);
608 }
609
610
461 // Emit code when ICData's targets are all Object == (which is ===). 611 // Emit code when ICData's targets are all Object == (which is ===).
462 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler, 612 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler,
463 const ICData& ic_data, 613 const ICData& ic_data,
464 const LocationSummary& locs, 614 const LocationSummary& locs,
465 Token::Kind kind, 615 Token::Kind kind,
466 BranchInstr* branch, 616 BranchInstr* branch,
467 intptr_t deopt_id) { 617 intptr_t deopt_id) {
468 UNIMPLEMENTED(); 618 UNIMPLEMENTED();
469 } 619 }
470 620
471 621
472 // First test if receiver is NULL, in which case === is applied. 622 // First test if receiver is NULL, in which case === is applied.
473 // If type feedback was provided (lists of <class-id, target>), do a 623 // If type feedback was provided (lists of <class-id, target>), do a
474 // type by type check (either === or static call to the operator. 624 // type by type check (either === or static call to the operator.
475 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, 625 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler,
476 LocationSummary* locs, 626 LocationSummary* locs,
477 Token::Kind kind, 627 Token::Kind kind,
478 BranchInstr* branch, 628 BranchInstr* branch,
479 const ICData& ic_data, 629 const ICData& ic_data,
480 intptr_t deopt_id, 630 intptr_t deopt_id,
481 intptr_t token_pos) { 631 intptr_t token_pos) {
482 UNIMPLEMENTED(); 632 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
483 } 633 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0));
634 Register left = locs->in(0).reg();
635 Register right = locs->in(1).reg();
636 Label done, identity_compare, non_null_compare;
637 __ TraceSimMsg("EmitGenericEqualityCompare");
638 __ beq(right, NULLREG, &identity_compare);
639 __ bne(left, NULLREG, &non_null_compare);
484 640
485 641 // Comparison with NULL is "===".
486 static Condition TokenKindToSmiCondition(Token::Kind kind) { 642 __ Bind(&identity_compare);
487 switch (kind) { 643 Condition cond = TokenKindToSmiCondition(kind);
488 case Token::kEQ: return EQ; 644 __ slt(CMPRES, left, right);
489 case Token::kNE: return NE; 645 __ slt(TMP1, right, left);
490 case Token::kLT: return LT; 646 if (branch != NULL) {
491 case Token::kGT: return GT; 647 branch->EmitBranchOnCondition(compiler, cond);
492 case Token::kLTE: return LE; 648 } else {
493 case Token::kGTE: return GE; 649 Register result = locs->out().reg();
494 default: 650 Label load_true;
495 UNREACHABLE(); 651 EmitBranchAfterCompare(compiler, cond, &load_true);
496 return VS; 652 __ LoadObject(result, Bool::False());
653 __ b(&done);
654 __ Bind(&load_true);
655 __ LoadObject(result, Bool::True());
497 } 656 }
498 } 657 __ b(&done);
499 658 __ Bind(&non_null_compare); // Receiver is not null.
500 659 ASSERT(left == A1);
501 // Branches on condition c assuming comparison results in CMPRES and TMP1. 660 ASSERT(right == A0);
502 static void EmitBranchAfterCompare( 661 __ addiu(SP, SP, Immediate(-2 * kWordSize));
503 FlowGraphCompiler* compiler, Condition c, Label* is_true) { 662 __ sw(A1, Address(SP, 1 * kWordSize));
504 switch (c) { 663 __ sw(A0, Address(SP, 0 * kWordSize));
505 case EQ: __ beq(CMPRES, TMP1, is_true); break; 664 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind,
506 case NE: __ bne(CMPRES, TMP1, is_true); break; 665 deopt_id, token_pos);
507 case GT: __ bne(TMP1, ZR, is_true); break; 666 __ Bind(&done);
508 case GE: __ beq(CMPRES, ZR, is_true); break;
509 case LT: __ bne(CMPRES, ZR, is_true); break;
510 case LE: __ beq(TMP1, ZR, is_true); break;
511 default:
512 UNREACHABLE();
513 break;
514 }
515 } 667 }
516 668
517 669
518 static Condition FlipCondition(Condition condition) { 670 static Condition FlipCondition(Condition condition) {
519 UNIMPLEMENTED(); 671 switch (condition) {
520 return condition; 672 case EQ: return EQ;
673 case NE: return NE;
674 case LT: return GT;
675 case LE: return GE;
676 case GT: return LT;
677 case GE: return LE;
678 default:
679 UNREACHABLE();
680 return EQ;
681 }
521 } 682 }
522 683
523 684
524 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, 685 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
525 const LocationSummary& locs, 686 const LocationSummary& locs,
526 Token::Kind kind, 687 Token::Kind kind,
527 BranchInstr* branch) { 688 BranchInstr* branch) {
528 __ TraceSimMsg("EmitSmiComparisonOp"); 689 __ TraceSimMsg("EmitSmiComparisonOp");
529 Location left = locs.in(0); 690 Location left = locs.in(0);
530 Location right = locs.in(1); 691 Location right = locs.in(1);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 } 766 }
606 if (IsPolymorphic()) { 767 if (IsPolymorphic()) {
607 EmitGenericEqualityCompare(compiler, locs(), kind(), kNoBranch, *ic_data(), 768 EmitGenericEqualityCompare(compiler, locs(), kind(), kNoBranch, *ic_data(),
608 deopt_id(), token_pos()); 769 deopt_id(), token_pos());
609 return; 770 return;
610 } 771 }
611 Register left = locs()->in(0).reg(); 772 Register left = locs()->in(0).reg();
612 Register right = locs()->in(1).reg(); 773 Register right = locs()->in(1).reg();
613 ASSERT(left == A1); 774 ASSERT(left == A1);
614 ASSERT(right == A0); 775 ASSERT(right == A0);
776 __ addiu(SP, SP, Immediate(-2 * kWordSize));
777 __ sw(A1, Address(SP, 1 * kWordSize));
778 __ sw(A0, Address(SP, 0 * kWordSize));
615 EmitEqualityAsInstanceCall(compiler, 779 EmitEqualityAsInstanceCall(compiler,
616 deopt_id(), 780 deopt_id(),
617 token_pos(), 781 token_pos(),
618 kind(), 782 kind(),
619 locs(), 783 locs(),
620 *ic_data()); 784 *ic_data());
621 ASSERT(locs()->out().reg() == V0); 785 ASSERT(locs()->out().reg() == V0);
622 } 786 }
623 787
624 788
(...skipping 23 matching lines...) Expand all
648 } 812 }
649 if (IsPolymorphic()) { 813 if (IsPolymorphic()) {
650 EmitGenericEqualityCompare(compiler, locs(), kind(), branch, *ic_data(), 814 EmitGenericEqualityCompare(compiler, locs(), kind(), branch, *ic_data(),
651 deopt_id(), token_pos()); 815 deopt_id(), token_pos());
652 return; 816 return;
653 } 817 }
654 Register left = locs()->in(0).reg(); 818 Register left = locs()->in(0).reg();
655 Register right = locs()->in(1).reg(); 819 Register right = locs()->in(1).reg();
656 ASSERT(left == A1); 820 ASSERT(left == A1);
657 ASSERT(right == A0); 821 ASSERT(right == A0);
822 __ addiu(SP, SP, Immediate(-2 * kWordSize));
823 __ sw(A1, Address(SP, 1 * kWordSize));
824 __ sw(A0, Address(SP, 0 * kWordSize));
658 EmitEqualityAsInstanceCall(compiler, 825 EmitEqualityAsInstanceCall(compiler,
659 deopt_id(), 826 deopt_id(),
660 token_pos(), 827 token_pos(),
661 Token::kEQ, // kNE reverse occurs at branch. 828 Token::kEQ, // kNE reverse occurs at branch.
662 locs(), 829 locs(),
663 *ic_data()); 830 *ic_data());
664 if (branch->is_checked()) { 831 if (branch->is_checked()) {
665 EmitAssertBoolean(V0, token_pos(), deopt_id(), locs(), compiler); 832 EmitAssertBoolean(V0, token_pos(), deopt_id(), locs(), compiler);
666 } 833 }
667 Condition branch_condition = (kind() == Token::kNE) ? NE : EQ; 834 Condition branch_condition = (kind() == Token::kNE) ? NE : EQ;
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
846 __ LoadImmediate(A1, NativeArguments::ComputeArgcTag(function())); 1013 __ LoadImmediate(A1, NativeArguments::ComputeArgcTag(function()));
847 compiler->GenerateCall(token_pos(), 1014 compiler->GenerateCall(token_pos(),
848 &StubCode::CallNativeCFunctionLabel(), 1015 &StubCode::CallNativeCFunctionLabel(),
849 PcDescriptors::kOther, 1016 PcDescriptors::kOther,
850 locs()); 1017 locs());
851 __ Pop(result); 1018 __ Pop(result);
852 } 1019 }
853 1020
854 1021
855 LocationSummary* StringFromCharCodeInstr::MakeLocationSummary() const { 1022 LocationSummary* StringFromCharCodeInstr::MakeLocationSummary() const {
856 UNIMPLEMENTED(); 1023 const intptr_t kNumInputs = 1;
857 return NULL; 1024 // TODO(fschneider): Allow immediate operands for the char code.
1025 return LocationSummary::Make(kNumInputs,
1026 Location::RequiresRegister(),
1027 LocationSummary::kNoCall);
858 } 1028 }
859 1029
860 1030
861 void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1031 void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
862 UNIMPLEMENTED(); 1032 Register char_code = locs()->in(0).reg();
1033 Register result = locs()->out().reg();
1034
1035 __ TraceSimMsg("StringFromCharCodeInstr");
1036
1037 __ LoadImmediate(result,
1038 reinterpret_cast<uword>(Symbols::PredefinedAddress()));
1039 __ AddImmediate(result, Symbols::kNullCharCodeSymbolOffset * kWordSize);
1040 __ sll(TMP1, char_code, 1); // Char code is a smi.
1041 __ addu(TMP1, TMP1, result);
1042 __ lw(result, Address(TMP1));
863 } 1043 }
864 1044
865 1045
866 LocationSummary* LoadUntaggedInstr::MakeLocationSummary() const { 1046 LocationSummary* LoadUntaggedInstr::MakeLocationSummary() const {
867 UNIMPLEMENTED(); 1047 UNIMPLEMENTED();
868 return NULL; 1048 return NULL;
869 } 1049 }
870 1050
871 1051
872 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1052 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
979 if (representation() == kUnboxedDouble) { 1159 if (representation() == kUnboxedDouble) {
980 locs->set_out(Location::RequiresFpuRegister()); 1160 locs->set_out(Location::RequiresFpuRegister());
981 } else { 1161 } else {
982 locs->set_out(Location::RequiresRegister()); 1162 locs->set_out(Location::RequiresRegister());
983 } 1163 }
984 return locs; 1164 return locs;
985 } 1165 }
986 1166
987 1167
988 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1168 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1169 __ TraceSimMsg("LoadIndexedInstr");
989 Register array = locs()->in(0).reg(); 1170 Register array = locs()->in(0).reg();
990 Location index = locs()->in(1); 1171 Location index = locs()->in(1);
991 1172
992 Address element_address(kNoRegister, 0); 1173 Address element_address(kNoRegister, 0);
993 if (IsExternal()) { 1174 if (IsExternal()) {
994 UNIMPLEMENTED(); 1175 UNIMPLEMENTED();
995 } else { 1176 } else {
996 ASSERT(this->array()->definition()->representation() == kTagged); 1177 ASSERT(this->array()->definition()->representation() == kTagged);
997 ASSERT(index.IsRegister()); // TODO(regis): Revisit. 1178 ASSERT(index.IsRegister()); // TODO(regis): Revisit.
998 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays 1179 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays
(...skipping 739 matching lines...) Expand 10 before | Expand all | Expand 10 after
1738 const ExternalLabel label("alloc_context", 1919 const ExternalLabel label("alloc_context",
1739 StubCode::AllocateContextEntryPoint()); 1920 StubCode::AllocateContextEntryPoint());
1740 compiler->GenerateCall(token_pos(), 1921 compiler->GenerateCall(token_pos(),
1741 &label, 1922 &label,
1742 PcDescriptors::kOther, 1923 PcDescriptors::kOther,
1743 locs()); 1924 locs());
1744 } 1925 }
1745 1926
1746 1927
1747 LocationSummary* CloneContextInstr::MakeLocationSummary() const { 1928 LocationSummary* CloneContextInstr::MakeLocationSummary() const {
1748 UNIMPLEMENTED(); 1929 const intptr_t kNumInputs = 1;
1749 return NULL; 1930 const intptr_t kNumTemps = 0;
1931 LocationSummary* locs =
1932 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
1933 locs->set_in(0, Location::RegisterLocation(T0));
1934 locs->set_out(Location::RegisterLocation(T0));
1935 return locs;
1750 } 1936 }
1751 1937
1752 1938
1753 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1939 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1754 UNIMPLEMENTED(); 1940 Register context_value = locs()->in(0).reg();
1941 Register result = locs()->out().reg();
1942
1943 __ TraceSimMsg("CloneContextInstr");
1944
1945 __ addiu(SP, SP, Immediate(-2 * kWordSize));
1946 __ LoadObject(TMP1, Object::ZoneHandle()); // Make room for the result.
1947 __ sw(TMP1, Address(SP, 1 * kWordSize));
1948 __ sw(context_value, Address(SP, 0 * kWordSize));
1949
1950 compiler->GenerateCallRuntime(token_pos(),
1951 deopt_id(),
1952 kCloneContextRuntimeEntry,
1953 locs());
1954 __ lw(result, Address(SP, 1 * kWordSize)); // Get result (cloned context).
1955 __ addiu(SP, SP, Immediate(2 * kWordSize));
1755 } 1956 }
1756 1957
1757 1958
1758 LocationSummary* CatchEntryInstr::MakeLocationSummary() const { 1959 LocationSummary* CatchEntryInstr::MakeLocationSummary() const {
1759 return LocationSummary::Make(0, 1960 return LocationSummary::Make(0,
1760 Location::NoLocation(), 1961 Location::NoLocation(),
1761 LocationSummary::kNoCall); 1962 LocationSummary::kNoCall);
1762 } 1963 }
1763 1964
1764 1965
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1843 2044
1844 __ LoadImmediate(TMP1, Isolate::Current()->stack_limit_address()); 2045 __ LoadImmediate(TMP1, Isolate::Current()->stack_limit_address());
1845 2046
1846 __ lw(TMP1, Address(TMP1)); 2047 __ lw(TMP1, Address(TMP1));
1847 __ BranchUnsignedLessEqual(SP, TMP1, slow_path->entry_label()); 2048 __ BranchUnsignedLessEqual(SP, TMP1, slow_path->entry_label());
1848 2049
1849 __ Bind(slow_path->exit_label()); 2050 __ Bind(slow_path->exit_label());
1850 } 2051 }
1851 2052
1852 2053
2054 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
2055 BinarySmiOpInstr* shift_left) {
2056 const bool is_truncating = shift_left->is_truncating();
2057 const LocationSummary& locs = *shift_left->locs();
2058 Register left = locs.in(0).reg();
2059 Register result = locs.out().reg();
2060 Label* deopt = shift_left->CanDeoptimize() ?
2061 compiler->AddDeoptStub(shift_left->deopt_id(), kDeoptBinarySmiOp) : NULL;
2062
2063 __ TraceSimMsg("EmitSmiShiftLeft");
2064
2065 if (locs.in(1).IsConstant()) {
2066 const Object& constant = locs.in(1).constant();
2067 ASSERT(constant.IsSmi());
2068 // Immediate shift operation takes 5 bits for the count.
2069 const intptr_t kCountLimit = 0x1F;
2070 const intptr_t value = Smi::Cast(constant).Value();
2071 if (value == 0) {
2072 // No code needed.
2073 } else if ((value < 0) || (value >= kCountLimit)) {
2074 // This condition may not be known earlier in some cases because
2075 // of constant propagation, inlining, etc.
2076 if ((value >= kCountLimit) && is_truncating) {
2077 __ mov(result, ZR);
2078 } else {
2079 // Result is Mint or exception.
2080 __ b(deopt);
2081 }
2082 } else {
2083 if (!is_truncating) {
2084 // Check for overflow (preserve left).
2085 __ sll(TMP1, left, value);
2086 __ sra(TMP1, TMP1, value);
2087 __ bne(TMP1, left, deopt); // Overflow.
2088 }
2089 // Shift for result now we know there is no overflow.
2090 __ sll(result, left, value);
2091 }
2092 return;
2093 }
2094
2095 // Right (locs.in(1)) is not constant.
2096 Register right = locs.in(1).reg();
2097 Range* right_range = shift_left->right()->definition()->range();
2098 if (shift_left->left()->BindsToConstant() && !is_truncating) {
2099 // TODO(srdjan): Implement code below for is_truncating().
2100 // If left is constant, we know the maximal allowed size for right.
2101 const Object& obj = shift_left->left()->BoundConstant();
2102 if (obj.IsSmi()) {
2103 const intptr_t left_int = Smi::Cast(obj).Value();
2104 if (left_int == 0) {
2105 __ bltz(right, deopt);
2106 return;
2107 }
2108 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
2109 const bool right_needs_check =
2110 (right_range == NULL) ||
2111 !right_range->IsWithin(0, max_right - 1);
2112 if (right_needs_check) {
2113 __ BranchUnsignedGreaterEqual(
2114 right, reinterpret_cast<int32_t>(Smi::New(max_right)), deopt);
2115 }
2116 __ SmiUntag(right);
2117 __ sllv(result, left, right);
2118 }
2119 return;
2120 }
2121
2122 const bool right_needs_check =
2123 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1));
2124 if (is_truncating) {
2125 if (right_needs_check) {
2126 const bool right_may_be_negative =
2127 (right_range == NULL) ||
2128 !right_range->IsWithin(0, RangeBoundary::kPlusInfinity);
2129 if (right_may_be_negative) {
2130 ASSERT(shift_left->CanDeoptimize());
2131 __ bltz(right, deopt);
2132 }
2133 Label done, is_not_zero;
2134
2135 __ sltiu(CMPRES,
2136 right, Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
2137 __ movz(result, ZR, CMPRES); // result = right >= kBits ? 0 : result.
2138 __ mov(TMP1, right);
2139 __ SmiUntag(TMP1);
2140 __ sllv(TMP1, left, TMP1);
2141 // result = right < kBits ? left << right : result.
2142 __ movn(result, TMP1, CMPRES);
2143 } else {
2144 __ SmiUntag(right);
2145 __ sllv(result, left, right);
2146 }
2147 } else {
2148 if (right_needs_check) {
2149 ASSERT(shift_left->CanDeoptimize());
2150 __ BranchUnsignedGreaterEqual(
2151 right, reinterpret_cast<int32_t>(Smi::New(Smi::kBits)), deopt);
2152 }
2153 // Left is not a constant.
2154 // Check if count too large for handling it inlined.
2155 __ SmiUntag(right);
2156 // Overflow test (preserve left and right);
2157 __ sllv(TMP1, left, right);
2158 __ srav(TMP1, TMP1, right);
2159 __ bne(TMP1, left, deopt); // Overflow.
2160 // Shift for result now we know there is no overflow.
2161 __ sllv(result, left, right);
2162 }
2163 }
2164
2165
1853 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { 2166 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const {
1854 const intptr_t kNumInputs = 2; 2167 const intptr_t kNumInputs = 2;
1855 if (op_kind() == Token::kTRUNCDIV) { 2168 if (op_kind() == Token::kTRUNCDIV) {
1856 UNIMPLEMENTED(); 2169 UNIMPLEMENTED();
1857 return NULL; 2170 return NULL;
1858 } else { 2171 } else {
1859 const intptr_t kNumTemps = op_kind() == Token::kADD ? 1 : 0; 2172 const intptr_t kNumTemps = op_kind() == Token::kADD ? 1 : 0;
1860 LocationSummary* summary = 2173 LocationSummary* summary =
1861 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2174 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1862 summary->set_in(0, Location::RequiresRegister()); 2175 summary->set_in(0, Location::RequiresRegister());
1863 summary->set_in(1, Location::RegisterOrSmiConstant(right())); 2176 summary->set_in(1, Location::RegisterOrSmiConstant(right()));
1864 if (op_kind() == Token::kADD) { 2177 if (op_kind() == Token::kADD) {
1865 // Need an extra temp for the overflow detection code. 2178 // Need an extra temp for the overflow detection code.
1866 summary->set_temp(0, Location::RequiresRegister()); 2179 summary->set_temp(0, Location::RequiresRegister());
1867 } 2180 }
1868 // We make use of 3-operand instructions by not requiring result register 2181 // We make use of 3-operand instructions by not requiring result register
1869 // to be identical to first input register as on Intel. 2182 // to be identical to first input register as on Intel.
1870 summary->set_out(Location::RequiresRegister()); 2183 summary->set_out(Location::RequiresRegister());
1871 return summary; 2184 return summary;
1872 } 2185 }
1873 } 2186 }
1874 2187
1875 2188
1876 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2189 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1877 __ TraceSimMsg("BinarySmiOpInstr"); 2190 __ TraceSimMsg("BinarySmiOpInstr");
1878 if (op_kind() == Token::kSHL) { 2191 if (op_kind() == Token::kSHL) {
1879 UNIMPLEMENTED(); 2192 EmitSmiShiftLeft(compiler, this);
1880 return; 2193 return;
1881 } 2194 }
1882 2195
1883 ASSERT(!is_truncating()); 2196 ASSERT(!is_truncating());
1884 Register left = locs()->in(0).reg(); 2197 Register left = locs()->in(0).reg();
1885 Register result = locs()->out().reg(); 2198 Register result = locs()->out().reg();
1886 Label* deopt = NULL; 2199 Label* deopt = NULL;
1887 if (CanDeoptimize()) { 2200 if (CanDeoptimize()) {
1888 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); 2201 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
1889 } 2202 }
1890 2203
1891 if (locs()->in(1).IsConstant()) { 2204 if (locs()->in(1).IsConstant()) {
1892 const Object& constant = locs()->in(1).constant(); 2205 const Object& constant = locs()->in(1).constant();
1893 ASSERT(constant.IsSmi()); 2206 ASSERT(constant.IsSmi());
1894 int32_t imm = reinterpret_cast<int32_t>(constant.raw()); 2207 int32_t imm = reinterpret_cast<int32_t>(constant.raw());
1895 switch (op_kind()) { 2208 switch (op_kind()) {
1896 case Token::kSUB: { 2209 case Token::kSUB: {
2210 __ TraceSimMsg("kSUB imm");
1897 if (deopt == NULL) { 2211 if (deopt == NULL) {
1898 __ AddImmediate(result, left, -imm); 2212 __ AddImmediate(result, left, -imm);
1899 } else { 2213 } else {
1900 __ SubImmediateDetectOverflow(result, left, imm, CMPRES); 2214 __ SubImmediateDetectOverflow(result, left, imm, CMPRES);
1901 __ bltz(CMPRES, deopt); 2215 __ bltz(CMPRES, deopt);
1902 } 2216 }
1903 break; 2217 break;
1904 } 2218 }
1905 case Token::kADD: { 2219 case Token::kADD: {
1906 if (deopt == NULL) { 2220 if (deopt == NULL) {
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1966 // No overflow check. 2280 // No overflow check.
1967 if (Utils::IsUint(kImmBits, imm)) { 2281 if (Utils::IsUint(kImmBits, imm)) {
1968 __ xori(result, left, Immediate(imm)); 2282 __ xori(result, left, Immediate(imm));
1969 } else { 2283 } else {
1970 __ LoadImmediate(TMP1, imm); 2284 __ LoadImmediate(TMP1, imm);
1971 __ xor_(result, left, TMP1); 2285 __ xor_(result, left, TMP1);
1972 } 2286 }
1973 break; 2287 break;
1974 } 2288 }
1975 case Token::kSHR: { 2289 case Token::kSHR: {
1976 UNIMPLEMENTED(); 2290 // sarl operation masks the count to 5 bits.
2291 const intptr_t kCountLimit = 0x1F;
2292 intptr_t value = Smi::Cast(constant).Value();
2293
2294 __ TraceSimMsg("kSHR");
2295
2296 if (value == 0) {
2297 // TODO(vegorov): should be handled outside.
2298 __ break_(0);
2299 break;
2300 } else if (value < 0) {
2301 // TODO(vegorov): should be handled outside.
2302 __ b(deopt);
2303 break;
2304 }
2305
2306 value = value + kSmiTagSize;
2307 if (value >= kCountLimit) value = kCountLimit;
2308
2309 __ sra(result, left, value);
2310 __ SmiTag(result);
1977 break; 2311 break;
1978 } 2312 }
1979 2313
1980 default: 2314 default:
1981 UNREACHABLE(); 2315 UNREACHABLE();
1982 break; 2316 break;
1983 } 2317 }
1984 return; 2318 return;
1985 } 2319 }
1986 2320
1987 Register right = locs()->in(1).reg(); 2321 Register right = locs()->in(1).reg();
1988 switch (op_kind()) { 2322 switch (op_kind()) {
1989 case Token::kADD: { 2323 case Token::kADD: {
1990 if (deopt == NULL) { 2324 if (deopt == NULL) {
1991 __ addu(result, left, right); 2325 __ addu(result, left, right);
1992 } else { 2326 } else {
1993 Register temp = locs()->temp(0).reg(); 2327 Register temp = locs()->temp(0).reg();
1994 __ AdduDetectOverflow(result, left, right, CMPRES, temp); 2328 __ AdduDetectOverflow(result, left, right, CMPRES, temp);
1995 __ bltz(CMPRES, deopt); 2329 __ bltz(CMPRES, deopt);
1996 } 2330 }
1997 break; 2331 break;
1998 } 2332 }
1999 case Token::kSUB: { 2333 case Token::kSUB: {
2334 __ TraceSimMsg("kSUB");
2000 if (deopt == NULL) { 2335 if (deopt == NULL) {
2001 __ subu(result, left, right); 2336 __ subu(result, left, right);
2002 } else { 2337 } else {
2003 __ SubuDetectOverflow(result, left, right, CMPRES); 2338 __ SubuDetectOverflow(result, left, right, CMPRES);
2004 __ bltz(CMPRES, deopt); 2339 __ bltz(CMPRES, deopt);
2005 } 2340 }
2006 break; 2341 break;
2007 } 2342 }
2008 case Token::kMUL: { 2343 case Token::kMUL: {
2344 __ TraceSimMsg("kMUL");
2009 __ SmiUntag(left); 2345 __ SmiUntag(left);
2010 __ mult(left, right); 2346 __ mult(left, right);
2011 __ mflo(result); 2347 __ mflo(result);
2012 if (deopt != NULL) { 2348 if (deopt != NULL) {
2013 UNIMPLEMENTED(); 2349 __ mfhi(TMP1);
2350 __ sra(CMPRES, result, 31);
2351 __ bne(TMP1, CMPRES, deopt);
2014 } 2352 }
2015 break; 2353 break;
2016 } 2354 }
2017 case Token::kBIT_AND: { 2355 case Token::kBIT_AND: {
2018 // No overflow check. 2356 // No overflow check.
2019 __ and_(result, left, right); 2357 __ and_(result, left, right);
2020 break; 2358 break;
2021 } 2359 }
2022 case Token::kBIT_OR: { 2360 case Token::kBIT_OR: {
2023 // No overflow check. 2361 // No overflow check.
(...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after
2435 UNIMPLEMENTED(); 2773 UNIMPLEMENTED();
2436 } 2774 }
2437 2775
2438 2776
2439 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { 2777 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const {
2440 return MakeCallSummary(); 2778 return MakeCallSummary();
2441 } 2779 }
2442 2780
2443 2781
2444 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2782 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2445 __ TraceSimMsg("PolymorphicInstanceCallInstr");
2446 Label* deopt = compiler->AddDeoptStub(deopt_id(), 2783 Label* deopt = compiler->AddDeoptStub(deopt_id(),
2447 kDeoptPolymorphicInstanceCallTestFail); 2784 kDeoptPolymorphicInstanceCallTestFail);
2785 __ TraceSimMsg("PolymorphicInstanceCallInstr");
2448 if (ic_data().NumberOfChecks() == 0) { 2786 if (ic_data().NumberOfChecks() == 0) {
2449 __ b(deopt); 2787 __ b(deopt);
2450 return; 2788 return;
2451 } 2789 }
2452 ASSERT(ic_data().num_args_tested() == 1); 2790 ASSERT(ic_data().num_args_tested() == 1);
2453 if (!with_checks()) { 2791 if (!with_checks()) {
2454 ASSERT(ic_data().HasOneTarget()); 2792 ASSERT(ic_data().HasOneTarget());
2455 const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0)); 2793 const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0));
2456 compiler->GenerateStaticCall(deopt_id(), 2794 compiler->GenerateStaticCall(deopt_id(),
2457 instance_call()->token_pos(), 2795 instance_call()->token_pos(),
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after
2819 } else { 3157 } else {
2820 compiler->EmitEqualityRegRegCompare(left.reg(), 3158 compiler->EmitEqualityRegRegCompare(left.reg(),
2821 right.reg(), 3159 right.reg(),
2822 needs_number_check(), 3160 needs_number_check(),
2823 token_pos()); 3161 token_pos());
2824 } 3162 }
2825 3163
2826 Register result = locs()->out().reg(); 3164 Register result = locs()->out().reg();
2827 Label load_true, done; 3165 Label load_true, done;
2828 if (kind() == Token::kEQ_STRICT) { 3166 if (kind() == Token::kEQ_STRICT) {
2829 __ beq(CMPRES, ZR, &load_true); 3167 __ beq(CMPRES, TMP1, &load_true);
2830 } else { 3168 } else {
2831 ASSERT(kind() == Token::kNE_STRICT); 3169 ASSERT(kind() == Token::kNE_STRICT);
2832 __ bne(CMPRES, ZR, &load_true); 3170 __ bne(CMPRES, TMP1, &load_true);
2833 } 3171 }
2834 __ LoadObject(result, Bool::False()); 3172 __ LoadObject(result, Bool::False());
2835 __ b(&done); 3173 __ b(&done);
2836 __ Bind(&load_true); 3174 __ Bind(&load_true);
2837 __ LoadObject(result, Bool::True()); 3175 __ LoadObject(result, Bool::True());
2838 __ Bind(&done); 3176 __ Bind(&done);
2839 } 3177 }
2840 3178
2841 3179
2842 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, 3180 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
2970 compiler->GenerateCall(token_pos(), 3308 compiler->GenerateCall(token_pos(),
2971 &label, 3309 &label,
2972 PcDescriptors::kOther, 3310 PcDescriptors::kOther,
2973 locs()); 3311 locs());
2974 __ Drop(2); // Discard type arguments and receiver. 3312 __ Drop(2); // Discard type arguments and receiver.
2975 } 3313 }
2976 3314
2977 } // namespace dart 3315 } // namespace dart
2978 3316
2979 #endif // defined TARGET_ARCH_MIPS 3317 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_arm.cc ('k') | runtime/vm/intrinsifier_arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698