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

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

Issue 64483002: Streamline code generator for branches and comparisons. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: added other platformd, comments addressed 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
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_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
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 309 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 case ABOVE: return BELOW_EQUAL; 320 case ABOVE: return BELOW_EQUAL;
321 case ABOVE_EQUAL: return BELOW; 321 case ABOVE_EQUAL: return BELOW;
322 default: 322 default:
323 UNIMPLEMENTED(); 323 UNIMPLEMENTED();
324 return EQUAL; 324 return EQUAL;
325 } 325 }
326 } 326 }
327 327
328 328
329 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, 329 static void EmitBranchOnCondition(FlowGraphCompiler* compiler,
330 TargetEntryInstr* true_successor, 330 Condition true_condition,
331 TargetEntryInstr* false_successor, 331 BranchLabels labels) {
332 Condition true_condition) { 332 if (labels.fall_through == labels.false_label) {
333 if (compiler->CanFallThroughTo(false_successor)) {
334 // If the next block is the false successor, fall through to it. 333 // If the next block is the false successor, fall through to it.
335 __ j(true_condition, compiler->GetJumpLabel(true_successor)); 334 __ j(true_condition, labels.true_label);
336 } else { 335 } else {
337 // If the next block is not the false successor, branch to it. 336 // If the next block is not the false successor, branch to it.
338 Condition false_condition = NegateCondition(true_condition); 337 Condition false_condition = NegateCondition(true_condition);
339 __ j(false_condition, compiler->GetJumpLabel(false_successor)); 338 __ j(false_condition, labels.false_label);
340 339
341 // Fall through or jump to the true successor. 340 // Fall through or jump to the true successor.
342 if (!compiler->CanFallThroughTo(true_successor)) { 341 if (labels.fall_through != labels.true_label) {
343 __ jmp(compiler->GetJumpLabel(true_successor)); 342 __ jmp(labels.true_label);
344 } 343 }
345 } 344 }
346 } 345 }
347 346
348 347
349 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, 348 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
350 const LocationSummary& locs, 349 const LocationSummary& locs,
351 Token::Kind kind, 350 Token::Kind kind,
352 BranchInstr* branch) { 351 BranchLabels labels) {
353 Location left = locs.in(0); 352 Location left = locs.in(0);
354 Location right = locs.in(1); 353 Location right = locs.in(1);
355 ASSERT(!left.IsConstant() || !right.IsConstant()); 354 ASSERT(!left.IsConstant() || !right.IsConstant());
356 355
357 Condition true_condition = TokenKindToSmiCondition(kind); 356 Condition true_condition = TokenKindToSmiCondition(kind);
358 357
359 if (left.IsConstant()) { 358 if (left.IsConstant()) {
360 __ CompareObject(right.reg(), left.constant()); 359 __ CompareObject(right.reg(), left.constant());
361 true_condition = FlipCondition(true_condition); 360 true_condition = FlipCondition(true_condition);
362 } else if (right.IsConstant()) { 361 } else if (right.IsConstant()) {
363 __ CompareObject(left.reg(), right.constant()); 362 __ CompareObject(left.reg(), right.constant());
364 } else if (right.IsStackSlot()) { 363 } else if (right.IsStackSlot()) {
365 __ cmpl(left.reg(), right.ToStackSlotAddress()); 364 __ cmpl(left.reg(), right.ToStackSlotAddress());
366 } else { 365 } else {
367 __ cmpl(left.reg(), right.reg()); 366 __ cmpl(left.reg(), right.reg());
368 } 367 }
369 368 EmitBranchOnCondition(compiler, true_condition, labels);
370 if (branch != NULL) {
371 EmitBranchOnCondition(compiler,
372 branch->true_successor(),
373 branch->false_successor(),
374 true_condition);
375 } else {
376 Register result = locs.out().reg();
377 Label done, is_true;
378 __ j(true_condition, &is_true);
379 __ LoadObject(result, Bool::False());
380 __ jmp(&done);
381 __ Bind(&is_true);
382 __ LoadObject(result, Bool::True());
383 __ Bind(&done);
384 }
385 } 369 }
386 370
387 371
388 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler, 372 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler,
389 Label* overflow, 373 Label* overflow,
390 XmmRegister result, 374 XmmRegister result,
391 Register tmp) { 375 Register tmp) {
392 // Compare upper half. 376 // Compare upper half.
393 Label check_lower, done; 377 Label check_lower, done;
394 __ pextrd(tmp, result, Immediate(1)); 378 __ pextrd(tmp, result, Immediate(1));
(...skipping 27 matching lines...) Expand all
422 default: 406 default:
423 UNREACHABLE(); 407 UNREACHABLE();
424 return OVERFLOW; 408 return OVERFLOW;
425 } 409 }
426 } 410 }
427 411
428 412
429 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, 413 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
430 const LocationSummary& locs, 414 const LocationSummary& locs,
431 Token::Kind kind, 415 Token::Kind kind,
432 BranchInstr* branch) { 416 BranchLabels labels) {
433 ASSERT(Token::IsEqualityOperator(kind)); 417 ASSERT(Token::IsEqualityOperator(kind));
434 XmmRegister left = locs.in(0).fpu_reg(); 418 XmmRegister left = locs.in(0).fpu_reg();
435 XmmRegister right = locs.in(1).fpu_reg(); 419 XmmRegister right = locs.in(1).fpu_reg();
436 Register temp = locs.temp(0).reg(); 420 Register temp = locs.temp(0).reg();
437 __ movaps(XMM0, left); 421 __ movaps(XMM0, left);
438 __ pcmpeqq(XMM0, right); 422 __ pcmpeqq(XMM0, right);
439 __ movd(temp, XMM0); 423 __ movd(temp, XMM0);
440 424
441 Condition true_condition = TokenKindToMintCondition(kind); 425 Condition true_condition = TokenKindToMintCondition(kind);
442 __ cmpl(temp, Immediate(-1)); 426 __ cmpl(temp, Immediate(-1));
443 427 EmitBranchOnCondition(compiler, true_condition, labels);
444 if (branch != NULL) {
445 EmitBranchOnCondition(compiler,
446 branch->true_successor(),
447 branch->false_successor(),
448 true_condition);
449 } else {
450 Register result = locs.out().reg();
451 Label done, is_true;
452 __ j(true_condition, &is_true);
453 __ LoadObject(result, Bool::False());
454 __ jmp(&done);
455 __ Bind(&is_true);
456 __ LoadObject(result, Bool::True());
457 __ Bind(&done);
458 }
459 } 428 }
460 429
461 430
462 static void EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, 431 static void EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
463 const LocationSummary& locs, 432 const LocationSummary& locs,
464 Token::Kind kind, 433 Token::Kind kind,
465 BranchInstr* branch) { 434 BranchLabels labels) {
466 XmmRegister left = locs.in(0).fpu_reg(); 435 XmmRegister left = locs.in(0).fpu_reg();
467 XmmRegister right = locs.in(1).fpu_reg(); 436 XmmRegister right = locs.in(1).fpu_reg();
468 Register left_tmp = locs.temp(0).reg(); 437 Register left_tmp = locs.temp(0).reg();
469 Register right_tmp = locs.temp(1).reg(); 438 Register right_tmp = locs.temp(1).reg();
470 Register result = branch == NULL ? locs.out().reg() : kNoRegister;
471 439
472 Condition hi_cond = OVERFLOW, lo_cond = OVERFLOW; 440 Condition hi_cond = OVERFLOW, lo_cond = OVERFLOW;
473 switch (kind) { 441 switch (kind) {
474 case Token::kLT: 442 case Token::kLT:
475 hi_cond = LESS; 443 hi_cond = LESS;
476 lo_cond = BELOW; 444 lo_cond = BELOW;
477 break; 445 break;
478 case Token::kGT: 446 case Token::kGT:
479 hi_cond = GREATER; 447 hi_cond = GREATER;
480 lo_cond = ABOVE; 448 lo_cond = ABOVE;
481 break; 449 break;
482 case Token::kLTE: 450 case Token::kLTE:
483 hi_cond = LESS; 451 hi_cond = LESS;
484 lo_cond = BELOW_EQUAL; 452 lo_cond = BELOW_EQUAL;
485 break; 453 break;
486 case Token::kGTE: 454 case Token::kGTE:
487 hi_cond = GREATER; 455 hi_cond = GREATER;
488 lo_cond = ABOVE_EQUAL; 456 lo_cond = ABOVE_EQUAL;
489 break; 457 break;
490 default: 458 default:
491 break; 459 break;
492 } 460 }
493 ASSERT(hi_cond != OVERFLOW && lo_cond != OVERFLOW); 461 ASSERT(hi_cond != OVERFLOW && lo_cond != OVERFLOW);
494 Label is_true, is_false; 462 Label is_true, is_false;
495 // Compare upper halves first. 463 // Compare upper halves first.
496 __ pextrd(left_tmp, left, Immediate(1)); 464 __ pextrd(left_tmp, left, Immediate(1));
497 __ pextrd(right_tmp, right, Immediate(1)); 465 __ pextrd(right_tmp, right, Immediate(1));
498 __ cmpl(left_tmp, right_tmp); 466 __ cmpl(left_tmp, right_tmp);
499 if (branch != NULL) { 467 __ j(hi_cond, labels.true_label);
500 __ j(hi_cond, compiler->GetJumpLabel(branch->true_successor())); 468 __ j(FlipCondition(hi_cond), labels.false_label);
501 __ j(FlipCondition(hi_cond),
502 compiler->GetJumpLabel(branch->false_successor()));
503 } else {
504 __ j(hi_cond, &is_true);
505 __ j(FlipCondition(hi_cond), &is_false);
506 }
507 469
508 // If upper is equal, compare lower half. 470 // If upper is equal, compare lower half.
509 __ pextrd(left_tmp, left, Immediate(0)); 471 __ pextrd(left_tmp, left, Immediate(0));
510 __ pextrd(right_tmp, right, Immediate(0)); 472 __ pextrd(right_tmp, right, Immediate(0));
511 __ cmpl(left_tmp, right_tmp); 473 __ cmpl(left_tmp, right_tmp);
512 if (branch != NULL) { 474 EmitBranchOnCondition(compiler, lo_cond, labels);
513 EmitBranchOnCondition(compiler,
514 branch->true_successor(),
515 branch->false_successor(),
516 lo_cond);
517 } else {
518 Label done;
519 __ j(lo_cond, &is_true);
520 __ Bind(&is_false);
521 __ LoadObject(result, Bool::False());
522 __ jmp(&done);
523 __ Bind(&is_true);
524 __ LoadObject(result, Bool::True());
525 __ Bind(&done);
526 }
527 } 475 }
528 476
529 477
530 static Condition TokenKindToDoubleCondition(Token::Kind kind) { 478 static Condition TokenKindToDoubleCondition(Token::Kind kind) {
531 switch (kind) { 479 switch (kind) {
532 case Token::kEQ: return EQUAL; 480 case Token::kEQ: return EQUAL;
533 case Token::kNE: return NOT_EQUAL; 481 case Token::kNE: return NOT_EQUAL;
534 case Token::kLT: return BELOW; 482 case Token::kLT: return BELOW;
535 case Token::kGT: return ABOVE; 483 case Token::kGT: return ABOVE;
536 case Token::kLTE: return BELOW_EQUAL; 484 case Token::kLTE: return BELOW_EQUAL;
537 case Token::kGTE: return ABOVE_EQUAL; 485 case Token::kGTE: return ABOVE_EQUAL;
538 default: 486 default:
539 UNREACHABLE(); 487 UNREACHABLE();
540 return OVERFLOW; 488 return OVERFLOW;
541 } 489 }
542 } 490 }
543 491
544 492
545 static void EmitDoubleCompareBranch(FlowGraphCompiler* compiler, 493 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
546 Condition true_condition, 494 const LocationSummary& locs,
547 FpuRegister left, 495 Token::Kind kind,
548 FpuRegister right, 496 BranchLabels labels) {
549 BranchInstr* branch) { 497 XmmRegister left = locs.in(0).fpu_reg();
550 ASSERT(branch != NULL); 498 XmmRegister right = locs.in(1).fpu_reg();
499
551 __ comisd(left, right); 500 __ comisd(left, right);
552 BlockEntryInstr* nan_result = (true_condition == NOT_EQUAL) ? 501
553 branch->true_successor() : branch->false_successor(); 502 Condition true_condition = TokenKindToDoubleCondition(kind);
554 __ j(PARITY_EVEN, compiler->GetJumpLabel(nan_result)); 503 Label* nan_result = (true_condition == NOT_EQUAL)
555 EmitBranchOnCondition(compiler, 504 ? labels.true_label : labels.false_label;
556 branch->true_successor(), 505 __ j(PARITY_EVEN, nan_result);
557 branch->false_successor(), 506 EmitBranchOnCondition(compiler, true_condition, labels);
558 true_condition);
559 } 507 }
560 508
561 509
510 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
511 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
562 512
563 static void EmitDoubleCompareBool(FlowGraphCompiler* compiler, 513 Label is_true, is_false;
564 Condition true_condition, 514 BranchLabels labels = { &is_true, &is_false, &is_false };
565 FpuRegister left, 515
566 FpuRegister right, 516 if (operation_cid() == kSmiCid) {
567 Register result) { 517 EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
568 __ comisd(left, right); 518 } else if (operation_cid() == kMintCid) {
569 Label is_false, is_true, done; 519 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels);
570 // x == NaN -> false, x != NaN -> true. 520 } else {
571 Label* nan_label = (true_condition == NOT_EQUAL) ? &is_true : &is_false; 521 ASSERT(operation_cid() == kDoubleCid);
572 __ j(PARITY_EVEN, nan_label, Assembler::kNearJump); 522 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
573 __ j(true_condition, &is_true, Assembler::kNearJump); 523 }
524 Register result = locs()->out().reg();
525 Label done;
574 __ Bind(&is_false); 526 __ Bind(&is_false);
575 __ LoadObject(result, Bool::False()); 527 __ LoadObject(result, Bool::False());
576 __ jmp(&done); 528 __ jmp(&done, Assembler::kNearJump);
577 __ Bind(&is_true); 529 __ Bind(&is_true);
578 __ LoadObject(result, Bool::True()); 530 __ LoadObject(result, Bool::True());
579 __ Bind(&done); 531 __ Bind(&done);
580 } 532 }
581 533
582 534
583 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, 535 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
584 const LocationSummary& locs, 536 BranchInstr* branch) {
585 Token::Kind kind, 537 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
586 BranchInstr* branch) {
587 XmmRegister left = locs.in(0).fpu_reg();
588 XmmRegister right = locs.in(1).fpu_reg();
589 538
590 Condition true_condition = TokenKindToDoubleCondition(kind); 539 BranchLabels labels = compiler->CreateBranchLabels(branch);
591 if (branch != NULL) { 540
592 EmitDoubleCompareBranch(compiler, true_condition, left, right, branch); 541 if (operation_cid() == kSmiCid) {
542 EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
543 } else if (operation_cid() == kMintCid) {
544 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels);
593 } else { 545 } else {
594 EmitDoubleCompareBool(compiler, true_condition, 546 ASSERT(operation_cid() == kDoubleCid);
595 left, right, locs.out().reg()); 547 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
596 } 548 }
597 } 549 }
598 550
599 551
600 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
601 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
602 BranchInstr* kNoBranch = NULL;
603 if (operation_cid() == kSmiCid) {
604 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch);
605 return;
606 }
607 if (operation_cid() == kMintCid) {
608 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), kNoBranch);
609 return;
610 }
611 if (operation_cid() == kDoubleCid) {
612 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch);
613 return;
614 }
615 UNREACHABLE();
616 }
617
618
619 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
620 BranchInstr* branch) {
621 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
622 if (operation_cid() == kSmiCid) {
623 EmitSmiComparisonOp(compiler, *locs(), kind(), branch);
624 return;
625 }
626 if (operation_cid() == kMintCid) {
627 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), branch);
628 return;
629 }
630 if (operation_cid() == kDoubleCid) {
631 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
632 return;
633 }
634 UNREACHABLE();
635 }
636
637
638 LocationSummary* TestSmiInstr::MakeLocationSummary() const { 552 LocationSummary* TestSmiInstr::MakeLocationSummary() const {
639 const intptr_t kNumInputs = 2; 553 const intptr_t kNumInputs = 2;
640 const intptr_t kNumTemps = 0; 554 const intptr_t kNumTemps = 0;
641 LocationSummary* locs = 555 LocationSummary* locs =
642 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 556 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
643 locs->set_in(0, Location::RequiresRegister()); 557 locs->set_in(0, Location::RequiresRegister());
644 // Only one input can be a constant operand. The case of two constant 558 // Only one input can be a constant operand. The case of two constant
645 // operands should be handled by constant propagation. 559 // operands should be handled by constant propagation.
646 locs->set_in(1, Location::RegisterOrConstant(right())); 560 locs->set_in(1, Location::RegisterOrConstant(right()));
647 return locs; 561 return locs;
648 } 562 }
649 563
650 564
651 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 565 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
652 // Never emitted outside of the BranchInstr. 566 // Never emitted outside of the BranchInstr.
653 UNREACHABLE(); 567 UNREACHABLE();
654 } 568 }
655 569
656 570
657 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, 571 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
658 BranchInstr* branch) { 572 BranchInstr* branch) {
659 Condition branch_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; 573 BranchLabels labels = compiler->CreateBranchLabels(branch);
574
575 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO;
660 Register left = locs()->in(0).reg(); 576 Register left = locs()->in(0).reg();
661 Location right = locs()->in(1); 577 Location right = locs()->in(1);
662 if (right.IsConstant()) { 578 if (right.IsConstant()) {
663 ASSERT(right.constant().IsSmi()); 579 ASSERT(right.constant().IsSmi());
664 const int32_t imm = 580 const int32_t imm =
665 reinterpret_cast<int32_t>(right.constant().raw()); 581 reinterpret_cast<int32_t>(right.constant().raw());
666 __ testl(left, Immediate(imm)); 582 __ testl(left, Immediate(imm));
667 } else { 583 } else {
668 __ testl(left, right.reg()); 584 __ testl(left, right.reg());
669 } 585 }
670 EmitBranchOnCondition(compiler, 586 EmitBranchOnCondition(compiler, true_condition, labels);
671 branch->true_successor(),
672 branch->false_successor(),
673 branch_condition);
674 } 587 }
675 588
676 589
677 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { 590 LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
678 const intptr_t kNumInputs = 2; 591 const intptr_t kNumInputs = 2;
679 const intptr_t kNumTemps = 0; 592 const intptr_t kNumTemps = 0;
680 if (operation_cid() == kMintCid) { 593 if (operation_cid() == kMintCid) {
681 const intptr_t kNumTemps = 2; 594 const intptr_t kNumTemps = 2;
682 LocationSummary* locs = 595 LocationSummary* locs =
683 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 596 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
(...skipping 20 matching lines...) Expand all
704 // operands should be handled by constant propagation. 617 // operands should be handled by constant propagation.
705 summary->set_in(1, summary->in(0).IsConstant() 618 summary->set_in(1, summary->in(0).IsConstant()
706 ? Location::RequiresRegister() 619 ? Location::RequiresRegister()
707 : Location::RegisterOrConstant(right())); 620 : Location::RegisterOrConstant(right()));
708 summary->set_out(Location::RequiresRegister()); 621 summary->set_out(Location::RequiresRegister());
709 return summary; 622 return summary;
710 } 623 }
711 624
712 625
713 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 626 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
627 Label is_true, is_false;
628 BranchLabels labels = { &is_true, &is_false, &is_false };
629
714 if (operation_cid() == kSmiCid) { 630 if (operation_cid() == kSmiCid) {
715 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL); 631 EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
716 return; 632 } else if (operation_cid() == kMintCid) {
633 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels);
634 } else {
635 ASSERT(operation_cid() == kDoubleCid);
636 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
717 } 637 }
718 if (operation_cid() == kMintCid) { 638 Register result = locs()->out().reg();
719 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), NULL); 639 Label done;
720 return; 640 __ Bind(&is_false);
721 } 641 __ LoadObject(result, Bool::False());
722 ASSERT(operation_cid() == kDoubleCid); 642 __ jmp(&done, Assembler::kNearJump);
723 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); 643 __ Bind(&is_true);
644 __ LoadObject(result, Bool::True());
645 __ Bind(&done);
724 } 646 }
725 647
726 648
727 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, 649 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
728 BranchInstr* branch) { 650 BranchInstr* branch) {
651 BranchLabels labels = compiler->CreateBranchLabels(branch);
652
729 if (operation_cid() == kSmiCid) { 653 if (operation_cid() == kSmiCid) {
730 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); 654 EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
731 return; 655 } else if (operation_cid() == kMintCid) {
656 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels);
657 } else {
658 ASSERT(operation_cid() == kDoubleCid);
659 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
732 } 660 }
733 if (operation_cid() == kMintCid) {
734 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch);
735 return;
736 }
737 ASSERT(operation_cid() == kDoubleCid);
738 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
739 } 661 }
740 662
741 663
742 LocationSummary* NativeCallInstr::MakeLocationSummary() const { 664 LocationSummary* NativeCallInstr::MakeLocationSummary() const {
743 const intptr_t kNumInputs = 0; 665 const intptr_t kNumInputs = 0;
744 const intptr_t kNumTemps = 3; 666 const intptr_t kNumTemps = 3;
745 LocationSummary* locs = 667 LocationSummary* locs =
746 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 668 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
747 locs->set_temp(0, Location::RegisterLocation(EAX)); 669 locs->set_temp(0, Location::RegisterLocation(EAX));
748 locs->set_temp(1, Location::RegisterLocation(ECX)); 670 locs->set_temp(1, Location::RegisterLocation(ECX));
(...skipping 3940 matching lines...) Expand 10 before | Expand all | Expand 10 after
4689 // Only one of the inputs can be a constant. Choose register if the first one 4611 // Only one of the inputs can be a constant. Choose register if the first one
4690 // is a constant. 4612 // is a constant.
4691 locs->set_in(1, locs->in(0).IsConstant() 4613 locs->set_in(1, locs->in(0).IsConstant()
4692 ? Location::RequiresRegister() 4614 ? Location::RequiresRegister()
4693 : Location::RegisterOrConstant(right())); 4615 : Location::RegisterOrConstant(right()));
4694 locs->set_out(Location::RequiresRegister()); 4616 locs->set_out(Location::RequiresRegister());
4695 return locs; 4617 return locs;
4696 } 4618 }
4697 4619
4698 4620
4621 static void EmitStrictComparison(FlowGraphCompiler* compiler,
4622 StrictCompareInstr* compare,
4623 BranchLabels labels) {
4624 LocationSummary* locs = compare->locs();
4625 bool needs_number_check = compare->needs_number_check();
4626 intptr_t token_pos = compare->token_pos();
4627 Token::Kind kind = compare->kind();
4628 Location left = locs->in(0);
4629 Location right = locs->in(1);
4630 ASSERT(!left.IsConstant() || !right.IsConstant());
4631 if (left.IsConstant()) {
4632 compiler->EmitEqualityRegConstCompare(right.reg(),
4633 left.constant(),
4634 needs_number_check,
4635 token_pos);
4636 } else if (right.IsConstant()) {
4637 compiler->EmitEqualityRegConstCompare(left.reg(),
4638 right.constant(),
4639 needs_number_check,
4640 token_pos);
4641 } else {
4642 compiler->EmitEqualityRegRegCompare(left.reg(),
4643 right.reg(),
4644 needs_number_check,
4645 token_pos);
4646 }
4647 Condition true_condition = (kind == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
4648 EmitBranchOnCondition(compiler, true_condition, labels);
4649 }
4650
4651
4699 // Special code for numbers (compare values instead of references.) 4652 // Special code for numbers (compare values instead of references.)
4700 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4653 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4701 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); 4654 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
4702 Location left = locs()->in(0); 4655
4703 Location right = locs()->in(1); 4656 Label is_true, is_false;
4704 ASSERT(!left.IsConstant() || !right.IsConstant()); 4657 BranchLabels labels = { &is_true, &is_false, &is_false };
4705 if (left.IsConstant()) { 4658
4706 compiler->EmitEqualityRegConstCompare(right.reg(), 4659 EmitStrictComparison(compiler, this, labels);
4707 left.constant(),
4708 needs_number_check(),
4709 token_pos());
4710 } else if (right.IsConstant()) {
4711 compiler->EmitEqualityRegConstCompare(left.reg(),
4712 right.constant(),
4713 needs_number_check(),
4714 token_pos());
4715 } else {
4716 compiler->EmitEqualityRegRegCompare(left.reg(),
4717 right.reg(),
4718 needs_number_check(),
4719 token_pos());
4720 }
4721 4660
4722 Register result = locs()->out().reg(); 4661 Register result = locs()->out().reg();
4723 Label load_true, done; 4662 Label done;
4724 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; 4663 __ Bind(&is_false);
4725 __ j(true_condition, &load_true, Assembler::kNearJump);
4726 __ LoadObject(result, Bool::False()); 4664 __ LoadObject(result, Bool::False());
4727 __ jmp(&done, Assembler::kNearJump); 4665 __ jmp(&done, Assembler::kNearJump);
4728 __ Bind(&load_true); 4666 __ Bind(&is_true);
4729 __ LoadObject(result, Bool::True()); 4667 __ LoadObject(result, Bool::True());
4730 __ Bind(&done); 4668 __ Bind(&done);
4731 } 4669 }
4732 4670
4733 4671
4734 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, 4672 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
4735 BranchInstr* branch) { 4673 BranchInstr* branch) {
4736 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); 4674 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
4737 Location left = locs()->in(0);
4738 Location right = locs()->in(1);
4739 ASSERT(!left.IsConstant() || !right.IsConstant());
4740 if (left.IsConstant()) {
4741 compiler->EmitEqualityRegConstCompare(right.reg(),
4742 left.constant(),
4743 needs_number_check(),
4744 token_pos());
4745 } else if (right.IsConstant()) {
4746 compiler->EmitEqualityRegConstCompare(left.reg(),
4747 right.constant(),
4748 needs_number_check(),
4749 token_pos());
4750 } else {
4751 compiler->EmitEqualityRegRegCompare(left.reg(),
4752 right.reg(),
4753 needs_number_check(),
4754 token_pos());
4755 }
4756 4675
4757 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; 4676 BranchLabels labels = compiler->CreateBranchLabels(branch);
4758 EmitBranchOnCondition(compiler, 4677
4759 branch->true_successor(), 4678 EmitStrictComparison(compiler, this, labels);
4760 branch->false_successor(),
4761 true_condition);
4762 } 4679 }
4763 4680
4764 4681
4765 // Detect pattern when one value is zero and another is a power of 2. 4682 // Detect pattern when one value is zero and another is a power of 2.
4766 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { 4683 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) {
4767 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || 4684 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) ||
4768 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); 4685 (Utils::IsPowerOfTwo(v2) && (v1 == 0));
4769 } 4686 }
4770 4687
4771 4688
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
4967 PcDescriptors::kOther, 4884 PcDescriptors::kOther,
4968 locs()); 4885 locs());
4969 __ Drop(2); // Discard type arguments and receiver. 4886 __ Drop(2); // Discard type arguments and receiver.
4970 } 4887 }
4971 4888
4972 } // namespace dart 4889 } // namespace dart
4973 4890
4974 #undef __ 4891 #undef __
4975 4892
4976 #endif // defined TARGET_ARCH_IA32 4893 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698