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

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

Issue 16048002: Fix equality code on ARM. (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/tests/vm/vm.status ('k') | no next file » | 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_ARM. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM.
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
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 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 LocationSummary* locs = 349 LocationSummary* locs =
350 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 350 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
351 locs->set_in(0, Location::RegisterLocation(R1)); 351 locs->set_in(0, Location::RegisterLocation(R1));
352 locs->set_in(1, Location::RegisterLocation(R0)); 352 locs->set_in(1, Location::RegisterLocation(R0));
353 locs->set_temp(0, Location::RegisterLocation(R5)); 353 locs->set_temp(0, Location::RegisterLocation(R5));
354 locs->set_out(Location::RegisterLocation(R0)); 354 locs->set_out(Location::RegisterLocation(R0));
355 return locs; 355 return locs;
356 } 356 }
357 357
358 358
359 // R1: left.
360 // R0: right.
361 // Uses R5 to load ic_call_data.
362 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, 359 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler,
363 intptr_t deopt_id, 360 intptr_t deopt_id,
364 intptr_t token_pos, 361 intptr_t token_pos,
365 Token::Kind kind, 362 Token::Kind kind,
366 LocationSummary* locs, 363 LocationSummary* locs,
367 const ICData& original_ic_data) { 364 const ICData& original_ic_data) {
368 if (!compiler->is_optimizing()) { 365 if (!compiler->is_optimizing()) {
369 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 366 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
370 deopt_id, 367 deopt_id,
371 token_pos); 368 token_pos);
372 } 369 }
373 const int kNumberOfArguments = 2; 370 const int kNumberOfArguments = 2;
374 const Array& kNoArgumentNames = Array::Handle(); 371 const Array& kNoArgumentNames = Array::Handle();
375 const int kNumArgumentsChecked = 2; 372 const int kNumArgumentsChecked = 2;
376 373
377 Label check_identity; 374 Label check_identity;
378 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); 375 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
376 __ ldm(IA, SP, (1 << R0) | (1 << R1));
379 __ cmp(R1, ShifterOperand(IP)); 377 __ cmp(R1, ShifterOperand(IP));
380 __ b(&check_identity, EQ); 378 __ b(&check_identity, EQ);
381 __ cmp(R0, ShifterOperand(IP)); 379 __ cmp(R0, ShifterOperand(IP));
382 __ b(&check_identity, EQ); 380 __ b(&check_identity, EQ);
383 381
384 ICData& equality_ic_data = ICData::ZoneHandle(); 382 ICData& equality_ic_data = ICData::ZoneHandle();
385 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { 383 if (compiler->is_optimizing() && FLAG_propagate_ic_data) {
386 ASSERT(!original_ic_data.IsNull()); 384 ASSERT(!original_ic_data.IsNull());
387 if (original_ic_data.NumberOfChecks() == 0) { 385 if (original_ic_data.NumberOfChecks() == 0) {
388 // IC call for reoptimization populates original ICData. 386 // IC call for reoptimization populates original ICData.
389 equality_ic_data = original_ic_data.raw(); 387 equality_ic_data = original_ic_data.raw();
390 } else { 388 } else {
391 // Megamorphic call. 389 // Megamorphic call.
392 equality_ic_data = original_ic_data.AsUnaryClassChecks(); 390 equality_ic_data = original_ic_data.AsUnaryClassChecks();
393 } 391 }
394 } else { 392 } else {
395 equality_ic_data = ICData::New(compiler->parsed_function().function(), 393 equality_ic_data = ICData::New(compiler->parsed_function().function(),
396 Symbols::EqualOperator(), 394 Symbols::EqualOperator(),
397 deopt_id, 395 deopt_id,
398 kNumArgumentsChecked); 396 kNumArgumentsChecked);
399 } 397 }
400 __ PushList((1 << R0) | (1 << R1));
401 compiler->GenerateInstanceCall(deopt_id, 398 compiler->GenerateInstanceCall(deopt_id,
402 token_pos, 399 token_pos,
403 kNumberOfArguments, 400 kNumberOfArguments,
404 kNoArgumentNames, 401 kNoArgumentNames,
405 locs, 402 locs,
406 equality_ic_data); 403 equality_ic_data);
407 Label check_ne; 404 Label check_ne;
408 __ b(&check_ne); 405 __ b(&check_ne);
409 406
410 __ Bind(&check_identity); 407 __ Bind(&check_identity);
411 Label equality_done; 408 Label equality_done;
412 if (compiler->is_optimizing()) { 409 if (compiler->is_optimizing()) {
413 // No need to update IC data. 410 // No need to update IC data.
411 __ PopList((1 << R0) | (1 << R1));
414 __ cmp(R0, ShifterOperand(R1)); 412 __ cmp(R0, ShifterOperand(R1));
415 __ LoadObject(R0, (kind == Token::kEQ) ? Bool::False() : Bool::True(), NE); 413 __ LoadObject(R0, (kind == Token::kEQ) ? Bool::False() : Bool::True(), NE);
416 __ LoadObject(R0, (kind == Token::kEQ) ? Bool::True() : Bool::False(), EQ); 414 __ LoadObject(R0, (kind == Token::kEQ) ? Bool::True() : Bool::False(), EQ);
417 if (kind == Token::kNE) { 415 if (kind == Token::kNE) {
418 // Skip not-equal result conversion. 416 // Skip not-equal result conversion.
419 __ b(&equality_done); 417 __ b(&equality_done);
420 } 418 }
421 } else { 419 } else {
422 // Call stub, load IC data in register. The stub will update ICData if 420 // Call stub, load IC data in register. The stub will update ICData if
423 // necessary. 421 // necessary.
424 Register ic_data_reg = locs->temp(0).reg(); 422 Register ic_data_reg = locs->temp(0).reg();
425 ASSERT(ic_data_reg == R5); // Stub depends on it. 423 ASSERT(ic_data_reg == R5); // Stub depends on it.
426 __ LoadObject(ic_data_reg, equality_ic_data); 424 __ LoadObject(ic_data_reg, equality_ic_data);
427 // Pass left in R1 and right in R0. 425 // Pass left in R1 and right in R0.
428 compiler->GenerateCall(token_pos, 426 compiler->GenerateCall(token_pos,
429 &StubCode::EqualityWithNullArgLabel(), 427 &StubCode::EqualityWithNullArgLabel(),
430 PcDescriptors::kRuntimeCall, 428 PcDescriptors::kRuntimeCall,
431 locs); 429 locs);
430 __ Drop(2);
432 } 431 }
433 __ Bind(&check_ne); 432 __ Bind(&check_ne);
434 if (kind == Token::kNE) { 433 if (kind == Token::kNE) {
435 // Negate the condition: true label returns false and vice versa. 434 // Negate the condition: true label returns false and vice versa.
436 __ CompareObject(R0, Bool::True()); 435 __ CompareObject(R0, Bool::True());
437 __ LoadObject(R0, Bool::True(), NE); 436 __ LoadObject(R0, Bool::True(), NE);
438 __ LoadObject(R0, Bool::False(), EQ); 437 __ LoadObject(R0, Bool::False(), EQ);
439 } 438 }
440 __ Bind(&equality_done); 439 __ Bind(&equality_done);
441 } 440 }
(...skipping 30 matching lines...) Expand all
472 case LS: return HI; 471 case LS: return HI;
473 case HI: return LS; 472 case HI: return LS;
474 case CS: return CC; 473 case CS: return CC;
475 default: 474 default:
476 UNIMPLEMENTED(); 475 UNIMPLEMENTED();
477 return EQ; 476 return EQ;
478 } 477 }
479 } 478 }
480 479
481 480
482 // R1: left. 481 // R1: left, also on stack.
483 // R0: right. 482 // R0: right, also on stack.
484 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, 483 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler,
485 const ICData& orig_ic_data, 484 const ICData& orig_ic_data,
486 LocationSummary* locs, 485 LocationSummary* locs,
487 BranchInstr* branch, 486 BranchInstr* branch,
488 Token::Kind kind, 487 Token::Kind kind,
489 intptr_t deopt_id, 488 intptr_t deopt_id,
490 intptr_t token_pos) { 489 intptr_t token_pos) {
491 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); 490 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
492 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); 491 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks());
493 ASSERT(ic_data.NumberOfChecks() > 0); 492 ASSERT(ic_data.NumberOfChecks() > 0);
(...skipping 17 matching lines...) Expand all
511 Label next_test; 510 Label next_test;
512 __ CompareImmediate(temp, ic_data.GetReceiverClassIdAt(i)); 511 __ CompareImmediate(temp, ic_data.GetReceiverClassIdAt(i));
513 if (i < len - 1) { 512 if (i < len - 1) {
514 __ b(&next_test, NE); 513 __ b(&next_test, NE);
515 } else { 514 } else {
516 __ b(deopt, NE); 515 __ b(deopt, NE);
517 } 516 }
518 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i)); 517 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i));
519 if (target.Owner() == object_store->object_class()) { 518 if (target.Owner() == object_store->object_class()) {
520 // Object.== is same as ===. 519 // Object.== is same as ===.
520 __ Drop(2);
521 __ cmp(left, ShifterOperand(right)); 521 __ cmp(left, ShifterOperand(right));
522 if (branch != NULL) { 522 if (branch != NULL) {
523 branch->EmitBranchOnCondition(compiler, cond); 523 branch->EmitBranchOnCondition(compiler, cond);
524 } else { 524 } else {
525 Register result = locs->out().reg(); 525 Register result = locs->out().reg();
526 __ LoadObject(result, Bool::True(), cond); 526 __ LoadObject(result, Bool::True(), cond);
527 __ LoadObject(result, Bool::False(), NegateCondition(cond)); 527 __ LoadObject(result, Bool::False(), NegateCondition(cond));
528 } 528 }
529 } else { 529 } else {
530 __ PushList((1 << R0) | (1 << R1));
531 const int kNumberOfArguments = 2; 530 const int kNumberOfArguments = 2;
532 const Array& kNoArgumentNames = Array::Handle(); 531 const Array& kNoArgumentNames = Array::Handle();
533 compiler->GenerateStaticCall(deopt_id, 532 compiler->GenerateStaticCall(deopt_id,
534 token_pos, 533 token_pos,
535 target, 534 target,
536 kNumberOfArguments, 535 kNumberOfArguments,
537 kNoArgumentNames, 536 kNoArgumentNames,
538 locs); 537 locs);
539 if (branch == NULL) { 538 if (branch == NULL) {
540 if (kind == Token::kNE) { 539 if (kind == Token::kNE) {
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
602 __ b(&load_true, cond); 601 __ b(&load_true, cond);
603 __ LoadObject(result, Bool::False()); 602 __ LoadObject(result, Bool::False());
604 __ b(&done); 603 __ b(&done);
605 __ Bind(&load_true); 604 __ Bind(&load_true);
606 __ LoadObject(result, Bool::True()); 605 __ LoadObject(result, Bool::True());
607 } 606 }
608 __ b(&done); 607 __ b(&done);
609 __ Bind(&non_null_compare); // Receiver is not null. 608 __ Bind(&non_null_compare); // Receiver is not null.
610 ASSERT(left == R1); 609 ASSERT(left == R1);
611 ASSERT(right == R0); 610 ASSERT(right == R0);
611 __ PushList((1 << R0) | (1 << R1));
612 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, 612 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind,
613 deopt_id, token_pos); 613 deopt_id, token_pos);
614 __ Bind(&done); 614 __ Bind(&done);
615 } 615 }
616 616
617 617
618 static Condition FlipCondition(Condition condition) { 618 static Condition FlipCondition(Condition condition) {
619 switch (condition) { 619 switch (condition) {
620 case EQ: return EQ; 620 case EQ: return EQ;
621 case NE: return NE; 621 case NE: return NE;
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
711 } 711 }
712 if (IsPolymorphic()) { 712 if (IsPolymorphic()) {
713 EmitGenericEqualityCompare(compiler, locs(), kind(), kNoBranch, *ic_data(), 713 EmitGenericEqualityCompare(compiler, locs(), kind(), kNoBranch, *ic_data(),
714 deopt_id(), token_pos()); 714 deopt_id(), token_pos());
715 return; 715 return;
716 } 716 }
717 Register left = locs()->in(0).reg(); 717 Register left = locs()->in(0).reg();
718 Register right = locs()->in(1).reg(); 718 Register right = locs()->in(1).reg();
719 ASSERT(left == R1); 719 ASSERT(left == R1);
720 ASSERT(right == R0); 720 ASSERT(right == R0);
721 __ PushList((1 << R0) | (1 << R1));
721 EmitEqualityAsInstanceCall(compiler, 722 EmitEqualityAsInstanceCall(compiler,
722 deopt_id(), 723 deopt_id(),
723 token_pos(), 724 token_pos(),
724 kind(), 725 kind(),
725 locs(), 726 locs(),
726 *ic_data()); 727 *ic_data());
727 ASSERT(locs()->out().reg() == R0); 728 ASSERT(locs()->out().reg() == R0);
728 } 729 }
729 730
730 731
(...skipping 22 matching lines...) Expand all
753 } 754 }
754 if (IsPolymorphic()) { 755 if (IsPolymorphic()) {
755 EmitGenericEqualityCompare(compiler, locs(), kind(), branch, *ic_data(), 756 EmitGenericEqualityCompare(compiler, locs(), kind(), branch, *ic_data(),
756 deopt_id(), token_pos()); 757 deopt_id(), token_pos());
757 return; 758 return;
758 } 759 }
759 Register left = locs()->in(0).reg(); 760 Register left = locs()->in(0).reg();
760 Register right = locs()->in(1).reg(); 761 Register right = locs()->in(1).reg();
761 ASSERT(left == R1); 762 ASSERT(left == R1);
762 ASSERT(right == R0); 763 ASSERT(right == R0);
764 __ PushList((1 << R0) | (1 << R1));
763 EmitEqualityAsInstanceCall(compiler, 765 EmitEqualityAsInstanceCall(compiler,
764 deopt_id(), 766 deopt_id(),
765 token_pos(), 767 token_pos(),
766 Token::kEQ, // kNE reverse occurs at branch. 768 Token::kEQ, // kNE reverse occurs at branch.
767 locs(), 769 locs(),
768 *ic_data()); 770 *ic_data());
769 if (branch->is_checked()) { 771 if (branch->is_checked()) {
770 EmitAssertBoolean(R0, token_pos(), deopt_id(), locs(), compiler); 772 EmitAssertBoolean(R0, token_pos(), deopt_id(), locs(), compiler);
771 } 773 }
772 Condition branch_condition = (kind() == Token::kNE) ? NE : EQ; 774 Condition branch_condition = (kind() == Token::kNE) ? NE : EQ;
(...skipping 2248 matching lines...) Expand 10 before | Expand all | Expand 10 after
3021 compiler->GenerateCall(token_pos(), 3023 compiler->GenerateCall(token_pos(),
3022 &label, 3024 &label,
3023 PcDescriptors::kOther, 3025 PcDescriptors::kOther,
3024 locs()); 3026 locs());
3025 __ Drop(2); // Discard type arguments and receiver. 3027 __ Drop(2); // Discard type arguments and receiver.
3026 } 3028 }
3027 3029
3028 } // namespace dart 3030 } // namespace dart
3029 3031
3030 #endif // defined TARGET_ARCH_ARM 3032 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/tests/vm/vm.status ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698