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

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: 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 | « no previous file | 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_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 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 case BELOW_EQUAL: return ABOVE; 319 case BELOW_EQUAL: return ABOVE;
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 struct BranchLabels {
330 Label* true_label;
331 Label* false_label;
332 Label* fall_through;
333 };
334
335
329 static void EmitBranchOnValue(FlowGraphCompiler* compiler, 336 static void EmitBranchOnValue(FlowGraphCompiler* compiler,
330 TargetEntryInstr* true_successor, 337 bool value,
331 TargetEntryInstr* false_successor, 338 BranchLabels labels) {
332 bool value) { 339 if (value && labels.fall_through != labels.true_label) {
Kevin Millikin (Google) 2013/11/07 14:34:09 I've actually gotten used to the extra parens arou
Florian Schneider 2013/11/08 12:00:20 Done.
333 if (value && !compiler->CanFallThroughTo(true_successor)) { 340 __ jmp(labels.true_label);
334 __ jmp(compiler->GetJumpLabel(true_successor)); 341 } else if (!value && labels.fall_through != labels.false_label) {
335 } else if (!value && !compiler->CanFallThroughTo(false_successor)) { 342 __ jmp(labels.false_label);
336 __ jmp(compiler->GetJumpLabel(false_successor));
337 } 343 }
338 } 344 }
339 345
340 346
341 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, 347 static void EmitBranchOnCondition(FlowGraphCompiler* compiler,
342 TargetEntryInstr* true_successor, 348 Condition true_condition,
343 TargetEntryInstr* false_successor, 349 BranchLabels labels) {
344 Condition true_condition) { 350 if (labels.fall_through == labels.false_label) {
345 if (compiler->CanFallThroughTo(false_successor)) {
346 // If the next block is the false successor, fall through to it. 351 // If the next block is the false successor, fall through to it.
347 __ j(true_condition, compiler->GetJumpLabel(true_successor)); 352 __ j(true_condition, labels.true_label);
348 } else { 353 } else {
349 // If the next block is not the false successor, branch to it. 354 // If the next block is not the false successor, branch to it.
350 Condition false_condition = NegateCondition(true_condition); 355 Condition false_condition = NegateCondition(true_condition);
351 __ j(false_condition, compiler->GetJumpLabel(false_successor)); 356 __ j(false_condition, labels.false_label);
352 357
353 // Fall through or jump to the true successor. 358 // Fall through or jump to the true successor.
354 if (!compiler->CanFallThroughTo(true_successor)) { 359 if (labels.fall_through != labels.true_label) {
355 __ jmp(compiler->GetJumpLabel(true_successor)); 360 __ jmp(labels.true_label);
356 } 361 }
357 } 362 }
358 } 363 }
359 364
360 365
361 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, 366 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
362 const LocationSummary& locs, 367 const LocationSummary& locs,
363 Token::Kind kind, 368 Token::Kind kind,
364 BranchInstr* branch) { 369 BranchLabels labels) {
365 Location left = locs.in(0); 370 Location left = locs.in(0);
366 Location right = locs.in(1); 371 Location right = locs.in(1);
367 ASSERT(!left.IsConstant() || !right.IsConstant()); 372 ASSERT(!left.IsConstant() || !right.IsConstant());
368 373
369 Condition true_condition = TokenKindToSmiCondition(kind); 374 Condition true_condition = TokenKindToSmiCondition(kind);
370 375
371 if (left.IsConstant()) { 376 if (left.IsConstant()) {
372 __ CompareObject(right.reg(), left.constant()); 377 __ CompareObject(right.reg(), left.constant());
373 true_condition = FlipCondition(true_condition); 378 true_condition = FlipCondition(true_condition);
374 } else if (right.IsConstant()) { 379 } else if (right.IsConstant()) {
375 __ CompareObject(left.reg(), right.constant()); 380 __ CompareObject(left.reg(), right.constant());
376 } else if (right.IsStackSlot()) { 381 } else if (right.IsStackSlot()) {
377 __ cmpl(left.reg(), right.ToStackSlotAddress()); 382 __ cmpl(left.reg(), right.ToStackSlotAddress());
378 } else { 383 } else {
379 __ cmpl(left.reg(), right.reg()); 384 __ cmpl(left.reg(), right.reg());
380 } 385 }
381 386 EmitBranchOnCondition(compiler, true_condition, labels);
382 if (branch != NULL) {
383 EmitBranchOnCondition(compiler,
384 branch->true_successor(),
385 branch->false_successor(),
386 true_condition);
387 } else {
388 Register result = locs.out().reg();
389 Label done, is_true;
390 __ j(true_condition, &is_true);
391 __ LoadObject(result, Bool::False());
392 __ jmp(&done);
393 __ Bind(&is_true);
394 __ LoadObject(result, Bool::True());
395 __ Bind(&done);
396 }
397 } 387 }
398 388
399 389
400 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler, 390 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler,
401 Label* overflow, 391 Label* overflow,
402 XmmRegister result, 392 XmmRegister result,
403 Register tmp) { 393 Register tmp) {
404 // Compare upper half. 394 // Compare upper half.
405 Label check_lower, done; 395 Label check_lower, done;
406 __ pextrd(tmp, result, Immediate(1)); 396 __ pextrd(tmp, result, Immediate(1));
(...skipping 27 matching lines...) Expand all
434 default: 424 default:
435 UNREACHABLE(); 425 UNREACHABLE();
436 return OVERFLOW; 426 return OVERFLOW;
437 } 427 }
438 } 428 }
439 429
440 430
441 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, 431 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
442 const LocationSummary& locs, 432 const LocationSummary& locs,
443 Token::Kind kind, 433 Token::Kind kind,
444 BranchInstr* branch) { 434 BranchLabels labels) {
445 ASSERT(Token::IsEqualityOperator(kind)); 435 ASSERT(Token::IsEqualityOperator(kind));
446 XmmRegister left = locs.in(0).fpu_reg(); 436 XmmRegister left = locs.in(0).fpu_reg();
447 XmmRegister right = locs.in(1).fpu_reg(); 437 XmmRegister right = locs.in(1).fpu_reg();
448 Register temp = locs.temp(0).reg(); 438 Register temp = locs.temp(0).reg();
449 __ movaps(XMM0, left); 439 __ movaps(XMM0, left);
450 __ pcmpeqq(XMM0, right); 440 __ pcmpeqq(XMM0, right);
451 __ movd(temp, XMM0); 441 __ movd(temp, XMM0);
452 442
453 Condition true_condition = TokenKindToMintCondition(kind); 443 Condition true_condition = TokenKindToMintCondition(kind);
454 __ cmpl(temp, Immediate(-1)); 444 __ cmpl(temp, Immediate(-1));
455 445 EmitBranchOnCondition(compiler, true_condition, labels);
456 if (branch != NULL) {
457 EmitBranchOnCondition(compiler,
458 branch->true_successor(),
459 branch->false_successor(),
460 true_condition);
461 } else {
462 Register result = locs.out().reg();
463 Label done, is_true;
464 __ j(true_condition, &is_true);
465 __ LoadObject(result, Bool::False());
466 __ jmp(&done);
467 __ Bind(&is_true);
468 __ LoadObject(result, Bool::True());
469 __ Bind(&done);
470 }
471 } 446 }
472 447
473 448
474 static void EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, 449 static void EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
475 const LocationSummary& locs, 450 const LocationSummary& locs,
476 Token::Kind kind, 451 Token::Kind kind,
477 BranchInstr* branch) { 452 BranchLabels labels) {
478 XmmRegister left = locs.in(0).fpu_reg(); 453 XmmRegister left = locs.in(0).fpu_reg();
479 XmmRegister right = locs.in(1).fpu_reg(); 454 XmmRegister right = locs.in(1).fpu_reg();
480 Register left_tmp = locs.temp(0).reg(); 455 Register left_tmp = locs.temp(0).reg();
481 Register right_tmp = locs.temp(1).reg(); 456 Register right_tmp = locs.temp(1).reg();
482 Register result = branch == NULL ? locs.out().reg() : kNoRegister;
483 457
484 Condition hi_cond = OVERFLOW, lo_cond = OVERFLOW; 458 Condition hi_cond = OVERFLOW, lo_cond = OVERFLOW;
485 switch (kind) { 459 switch (kind) {
486 case Token::kLT: 460 case Token::kLT:
487 hi_cond = LESS; 461 hi_cond = LESS;
488 lo_cond = BELOW; 462 lo_cond = BELOW;
489 break; 463 break;
490 case Token::kGT: 464 case Token::kGT:
491 hi_cond = GREATER; 465 hi_cond = GREATER;
492 lo_cond = ABOVE; 466 lo_cond = ABOVE;
493 break; 467 break;
494 case Token::kLTE: 468 case Token::kLTE:
495 hi_cond = LESS; 469 hi_cond = LESS;
496 lo_cond = BELOW_EQUAL; 470 lo_cond = BELOW_EQUAL;
497 break; 471 break;
498 case Token::kGTE: 472 case Token::kGTE:
499 hi_cond = GREATER; 473 hi_cond = GREATER;
500 lo_cond = ABOVE_EQUAL; 474 lo_cond = ABOVE_EQUAL;
501 break; 475 break;
502 default: 476 default:
503 break; 477 break;
504 } 478 }
505 ASSERT(hi_cond != OVERFLOW && lo_cond != OVERFLOW); 479 ASSERT(hi_cond != OVERFLOW && lo_cond != OVERFLOW);
506 Label is_true, is_false; 480 Label is_true, is_false;
507 // Compare upper halves first. 481 // Compare upper halves first.
508 __ pextrd(left_tmp, left, Immediate(1)); 482 __ pextrd(left_tmp, left, Immediate(1));
509 __ pextrd(right_tmp, right, Immediate(1)); 483 __ pextrd(right_tmp, right, Immediate(1));
510 __ cmpl(left_tmp, right_tmp); 484 __ cmpl(left_tmp, right_tmp);
511 if (branch != NULL) { 485 __ j(hi_cond, labels.true_label);
512 __ j(hi_cond, compiler->GetJumpLabel(branch->true_successor())); 486 __ j(FlipCondition(hi_cond), labels.false_label);
513 __ j(FlipCondition(hi_cond),
514 compiler->GetJumpLabel(branch->false_successor()));
515 } else {
516 __ j(hi_cond, &is_true);
517 __ j(FlipCondition(hi_cond), &is_false);
518 }
519 487
520 // If upper is equal, compare lower half. 488 // If upper is equal, compare lower half.
521 __ pextrd(left_tmp, left, Immediate(0)); 489 __ pextrd(left_tmp, left, Immediate(0));
522 __ pextrd(right_tmp, right, Immediate(0)); 490 __ pextrd(right_tmp, right, Immediate(0));
523 __ cmpl(left_tmp, right_tmp); 491 __ cmpl(left_tmp, right_tmp);
524 if (branch != NULL) { 492 EmitBranchOnCondition(compiler, lo_cond, labels);
525 EmitBranchOnCondition(compiler,
526 branch->true_successor(),
527 branch->false_successor(),
528 lo_cond);
529 } else {
530 Label done;
531 __ j(lo_cond, &is_true);
532 __ Bind(&is_false);
533 __ LoadObject(result, Bool::False());
534 __ jmp(&done);
535 __ Bind(&is_true);
536 __ LoadObject(result, Bool::True());
537 __ Bind(&done);
538 }
539 } 493 }
540 494
541 495
542 static Condition TokenKindToDoubleCondition(Token::Kind kind) { 496 static Condition TokenKindToDoubleCondition(Token::Kind kind) {
543 switch (kind) { 497 switch (kind) {
544 case Token::kEQ: return EQUAL; 498 case Token::kEQ: return EQUAL;
545 case Token::kNE: return NOT_EQUAL; 499 case Token::kNE: return NOT_EQUAL;
546 case Token::kLT: return BELOW; 500 case Token::kLT: return BELOW;
547 case Token::kGT: return ABOVE; 501 case Token::kGT: return ABOVE;
548 case Token::kLTE: return BELOW_EQUAL; 502 case Token::kLTE: return BELOW_EQUAL;
549 case Token::kGTE: return ABOVE_EQUAL; 503 case Token::kGTE: return ABOVE_EQUAL;
550 default: 504 default:
551 UNREACHABLE(); 505 UNREACHABLE();
552 return OVERFLOW; 506 return OVERFLOW;
553 } 507 }
554 } 508 }
555 509
556 510
557 static void EmitDoubleCompareBranch(FlowGraphCompiler* compiler, 511 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
558 Condition true_condition, 512 const LocationSummary& locs,
559 FpuRegister left, 513 Token::Kind kind,
560 FpuRegister right, 514 BranchLabels labels) {
561 BranchInstr* branch) { 515 XmmRegister left = locs.in(0).fpu_reg();
562 ASSERT(branch != NULL); 516 XmmRegister right = locs.in(1).fpu_reg();
517
563 __ comisd(left, right); 518 __ comisd(left, right);
564 BlockEntryInstr* nan_result = (true_condition == NOT_EQUAL) ? 519
565 branch->true_successor() : branch->false_successor(); 520 Condition true_condition = TokenKindToDoubleCondition(kind);
566 __ j(PARITY_EVEN, compiler->GetJumpLabel(nan_result)); 521 Label* nan_result = (true_condition == NOT_EQUAL)
567 EmitBranchOnCondition(compiler, 522 ? labels.true_label : labels.false_label;
568 branch->true_successor(), 523 __ j(PARITY_EVEN, nan_result);
569 branch->false_successor(), 524 EmitBranchOnCondition(compiler, true_condition, labels);
570 true_condition);
571 } 525 }
572 526
573 527
528 static BranchLabels CreateBranchLabels(FlowGraphCompiler* compiler,
529 BranchInstr* branch) {
530 Label* true_label = compiler->GetJumpLabel(branch->true_successor());
531 Label* false_label = compiler->GetJumpLabel(branch->false_successor());
532 Label* fall_through = compiler->CanFallThroughTo(branch->true_successor())
Kevin Millikin (Google) 2013/11/07 14:34:09 Hmmm, that's kind of ugly. What about a function
Florian Schneider 2013/11/08 12:00:20 Agreed. CanFallThroughTo uses next_nonempty_label
533 ? true_label : compiler->CanFallThroughTo(branch->false_successor())
534 ? false_label : NULL;
535 BranchLabels result = { true_label, false_label, fall_through };
536 return result;
537 }
574 538
575 static void EmitDoubleCompareBool(FlowGraphCompiler* compiler, 539
576 Condition true_condition, 540 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
577 FpuRegister left, 541 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
578 FpuRegister right, 542
579 Register result) { 543 Label is_true, is_false;
580 __ comisd(left, right); 544 BranchLabels labels = { &is_true, &is_false, &is_false };
581 Label is_false, is_true, done; 545
582 // x == NaN -> false, x != NaN -> true. 546 if (operation_cid() == kSmiCid) {
583 Label* nan_label = (true_condition == NOT_EQUAL) ? &is_true : &is_false; 547 EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
584 __ j(PARITY_EVEN, nan_label, Assembler::kNearJump); 548 } else if (operation_cid() == kMintCid) {
585 __ j(true_condition, &is_true, Assembler::kNearJump); 549 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels);
550 } else {
551 ASSERT(operation_cid() == kDoubleCid);
552 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
553 }
554 Register result = locs()->out().reg();
555 Label done;
586 __ Bind(&is_false); 556 __ Bind(&is_false);
587 __ LoadObject(result, Bool::False()); 557 __ LoadObject(result, Bool::False());
588 __ jmp(&done); 558 __ jmp(&done, Assembler::kNearJump);
589 __ Bind(&is_true); 559 __ Bind(&is_true);
590 __ LoadObject(result, Bool::True()); 560 __ LoadObject(result, Bool::True());
591 __ Bind(&done); 561 __ Bind(&done);
592 } 562 }
593 563
594 564
595 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, 565 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
596 const LocationSummary& locs, 566 BranchInstr* branch) {
597 Token::Kind kind, 567 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
598 BranchInstr* branch) {
599 XmmRegister left = locs.in(0).fpu_reg();
600 XmmRegister right = locs.in(1).fpu_reg();
601 568
602 Condition true_condition = TokenKindToDoubleCondition(kind); 569 BranchLabels labels = CreateBranchLabels(compiler, branch);
603 if (branch != NULL) { 570
604 EmitDoubleCompareBranch(compiler, true_condition, left, right, branch); 571 if (operation_cid() == kSmiCid) {
572 EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
573 } else if (operation_cid() == kMintCid) {
574 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels);
605 } else { 575 } else {
606 EmitDoubleCompareBool(compiler, true_condition, 576 ASSERT(operation_cid() == kDoubleCid);
607 left, right, locs.out().reg()); 577 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
608 } 578 }
609 } 579 }
610 580
611 581
612 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
613 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
614 BranchInstr* kNoBranch = NULL;
615 if (operation_cid() == kSmiCid) {
616 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch);
617 return;
618 }
619 if (operation_cid() == kMintCid) {
620 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), kNoBranch);
621 return;
622 }
623 if (operation_cid() == kDoubleCid) {
624 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch);
625 return;
626 }
627 UNREACHABLE();
628 }
629
630
631 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
632 BranchInstr* branch) {
633 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
634 if (operation_cid() == kSmiCid) {
635 // Deoptimizes if both arguments not Smi.
636 EmitSmiComparisonOp(compiler, *locs(), kind(), branch);
637 return;
638 }
639 if (operation_cid() == kMintCid) {
640 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), branch);
641 return;
642 }
643 if (operation_cid() == kDoubleCid) {
644 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
645 return;
646 }
647 UNREACHABLE();
648 }
649
650
651 LocationSummary* TestSmiInstr::MakeLocationSummary() const { 582 LocationSummary* TestSmiInstr::MakeLocationSummary() const {
652 const intptr_t kNumInputs = 2; 583 const intptr_t kNumInputs = 2;
653 const intptr_t kNumTemps = 0; 584 const intptr_t kNumTemps = 0;
654 LocationSummary* locs = 585 LocationSummary* locs =
655 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 586 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
656 locs->set_in(0, Location::RequiresRegister()); 587 locs->set_in(0, Location::RequiresRegister());
657 // Only one input can be a constant operand. The case of two constant 588 // Only one input can be a constant operand. The case of two constant
658 // operands should be handled by constant propagation. 589 // operands should be handled by constant propagation.
659 locs->set_in(1, Location::RegisterOrConstant(right())); 590 locs->set_in(1, Location::RegisterOrConstant(right()));
660 return locs; 591 return locs;
661 } 592 }
662 593
663 594
664 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 595 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
665 // Never emitted outside of the BranchInstr. 596 // Never emitted outside of the BranchInstr.
666 UNREACHABLE(); 597 UNREACHABLE();
667 } 598 }
668 599
669 600
670 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, 601 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
671 BranchInstr* branch) { 602 BranchInstr* branch) {
672 Condition branch_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; 603 BranchLabels labels = CreateBranchLabels(compiler, branch);
604
605 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO;
673 Register left = locs()->in(0).reg(); 606 Register left = locs()->in(0).reg();
674 Location right = locs()->in(1); 607 Location right = locs()->in(1);
675 if (right.IsConstant()) { 608 if (right.IsConstant()) {
676 ASSERT(right.constant().IsSmi()); 609 ASSERT(right.constant().IsSmi());
677 const int32_t imm = 610 const int32_t imm =
678 reinterpret_cast<int32_t>(right.constant().raw()); 611 reinterpret_cast<int32_t>(right.constant().raw());
679 __ testl(left, Immediate(imm)); 612 __ testl(left, Immediate(imm));
680 } else { 613 } else {
681 __ testl(left, right.reg()); 614 __ testl(left, right.reg());
682 } 615 }
683 EmitBranchOnCondition(compiler, 616 EmitBranchOnCondition(compiler, true_condition, labels);
684 branch->true_successor(),
685 branch->false_successor(),
686 branch_condition);
687 } 617 }
688 618
689 619
690 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { 620 LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
691 const intptr_t kNumInputs = 2; 621 const intptr_t kNumInputs = 2;
692 const intptr_t kNumTemps = 0; 622 const intptr_t kNumTemps = 0;
693 if (operation_cid() == kMintCid) { 623 if (operation_cid() == kMintCid) {
694 const intptr_t kNumTemps = 2; 624 const intptr_t kNumTemps = 2;
695 LocationSummary* locs = 625 LocationSummary* locs =
696 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 626 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
(...skipping 20 matching lines...) Expand all
717 // operands should be handled by constant propagation. 647 // operands should be handled by constant propagation.
718 summary->set_in(1, summary->in(0).IsConstant() 648 summary->set_in(1, summary->in(0).IsConstant()
719 ? Location::RequiresRegister() 649 ? Location::RequiresRegister()
720 : Location::RegisterOrConstant(right())); 650 : Location::RegisterOrConstant(right()));
721 summary->set_out(Location::RequiresRegister()); 651 summary->set_out(Location::RequiresRegister());
722 return summary; 652 return summary;
723 } 653 }
724 654
725 655
726 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 656 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
657 Label is_true, is_false;
658 BranchLabels labels = { &is_true, &is_false, &is_false };
659
727 if (operation_cid() == kSmiCid) { 660 if (operation_cid() == kSmiCid) {
728 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL); 661 EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
729 return; 662 } else if (operation_cid() == kMintCid) {
663 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels);
664 } else {
665 ASSERT(operation_cid() == kDoubleCid);
666 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
730 } 667 }
731 if (operation_cid() == kMintCid) { 668 Register result = locs()->out().reg();
732 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), NULL); 669 Label done;
733 return; 670 __ Bind(&is_false);
734 } 671 __ LoadObject(result, Bool::False());
735 ASSERT(operation_cid() == kDoubleCid); 672 __ jmp(&done, Assembler::kNearJump);
736 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); 673 __ Bind(&is_true);
674 __ LoadObject(result, Bool::True());
675 __ Bind(&done);
737 } 676 }
738 677
739 678
740 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, 679 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
741 BranchInstr* branch) { 680 BranchInstr* branch) {
681 BranchLabels labels = CreateBranchLabels(compiler, branch);
682
742 if (operation_cid() == kSmiCid) { 683 if (operation_cid() == kSmiCid) {
743 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); 684 EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
744 return; 685 } else if (operation_cid() == kMintCid) {
686 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels);
687 } else {
688 ASSERT(operation_cid() == kDoubleCid);
689 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
745 } 690 }
746 if (operation_cid() == kMintCid) {
747 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch);
748 return;
749 }
750 ASSERT(operation_cid() == kDoubleCid);
751 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
752 } 691 }
753 692
754 693
755 LocationSummary* NativeCallInstr::MakeLocationSummary() const { 694 LocationSummary* NativeCallInstr::MakeLocationSummary() const {
756 const intptr_t kNumInputs = 0; 695 const intptr_t kNumInputs = 0;
757 const intptr_t kNumTemps = 3; 696 const intptr_t kNumTemps = 3;
758 LocationSummary* locs = 697 LocationSummary* locs =
759 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 698 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
760 locs->set_temp(0, Location::RegisterLocation(EAX)); 699 locs->set_temp(0, Location::RegisterLocation(EAX));
761 locs->set_temp(1, Location::RegisterLocation(ECX)); 700 locs->set_temp(1, Location::RegisterLocation(ECX));
(...skipping 3887 matching lines...) Expand 10 before | Expand all | Expand 10 after
4649 const intptr_t kNumTemps = 0; 4588 const intptr_t kNumTemps = 0;
4650 LocationSummary* locs = 4589 LocationSummary* locs =
4651 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 4590 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
4652 locs->set_in(0, Location::RegisterOrConstant(left())); 4591 locs->set_in(0, Location::RegisterOrConstant(left()));
4653 locs->set_in(1, Location::RegisterOrConstant(right())); 4592 locs->set_in(1, Location::RegisterOrConstant(right()));
4654 locs->set_out(Location::RequiresRegister()); 4593 locs->set_out(Location::RequiresRegister());
4655 return locs; 4594 return locs;
4656 } 4595 }
4657 4596
4658 4597
4598 static void EmitStrictComparison(FlowGraphCompiler* compiler,
4599 StrictCompareInstr* compare,
4600 BranchLabels labels) {
4601 LocationSummary* locs = compare->locs();
4602 bool needs_number_check = compare->needs_number_check();
4603 intptr_t token_pos = compare->token_pos();
4604 Token::Kind kind = compare->kind();
4605 Location left = locs->in(0);
4606 Location right = locs->in(1);
4607 if (left.IsConstant() && right.IsConstant()) {
4608 // TODO(vegorov): should be eliminated earlier by constant propagation.
4609 const bool result = (kind == Token::kEQ_STRICT) ?
4610 left.constant().raw() == right.constant().raw() :
4611 left.constant().raw() != right.constant().raw();
4612 EmitBranchOnValue(compiler, result, labels);
4613 return;
4614 }
4615 if (left.IsConstant()) {
4616 compiler->EmitEqualityRegConstCompare(right.reg(),
4617 left.constant(),
4618 needs_number_check,
4619 token_pos);
4620 } else if (right.IsConstant()) {
4621 compiler->EmitEqualityRegConstCompare(left.reg(),
4622 right.constant(),
4623 needs_number_check,
4624 token_pos);
4625 } else {
4626 compiler->EmitEqualityRegRegCompare(left.reg(),
4627 right.reg(),
4628 needs_number_check,
4629 token_pos);
4630 }
4631 Condition true_condition = (kind == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
4632 EmitBranchOnCondition(compiler, true_condition, labels);
4633 }
4634
4635
4659 // Special code for numbers (compare values instead of references.) 4636 // Special code for numbers (compare values instead of references.)
4660 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4637 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4661 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); 4638 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
4662 Location left = locs()->in(0); 4639
4663 Location right = locs()->in(1); 4640 Label is_true, is_false;
4664 if (left.IsConstant() && right.IsConstant()) { 4641 BranchLabels labels = { &is_true, &is_false, &is_false };
4665 // TODO(vegorov): should be eliminated earlier by constant propagation. 4642
4666 const bool result = (kind() == Token::kEQ_STRICT) ? 4643 EmitStrictComparison(compiler, this, labels);
4667 left.constant().raw() == right.constant().raw() :
4668 left.constant().raw() != right.constant().raw();
4669 __ LoadObject(locs()->out().reg(), Bool::Get(result));
4670 return;
4671 }
4672 if (left.IsConstant()) {
4673 compiler->EmitEqualityRegConstCompare(right.reg(),
4674 left.constant(),
4675 needs_number_check(),
4676 token_pos());
4677 } else if (right.IsConstant()) {
4678 compiler->EmitEqualityRegConstCompare(left.reg(),
4679 right.constant(),
4680 needs_number_check(),
4681 token_pos());
4682 } else {
4683 compiler->EmitEqualityRegRegCompare(left.reg(),
4684 right.reg(),
4685 needs_number_check(),
4686 token_pos());
4687 }
4688 4644
4689 Register result = locs()->out().reg(); 4645 Register result = locs()->out().reg();
4690 Label load_true, done; 4646 Label done;
4691 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; 4647 __ Bind(&is_false);
4692 __ j(true_condition, &load_true, Assembler::kNearJump);
4693 __ LoadObject(result, Bool::False()); 4648 __ LoadObject(result, Bool::False());
4694 __ jmp(&done, Assembler::kNearJump); 4649 __ jmp(&done, Assembler::kNearJump);
4695 __ Bind(&load_true); 4650 __ Bind(&is_true);
4696 __ LoadObject(result, Bool::True()); 4651 __ LoadObject(result, Bool::True());
4697 __ Bind(&done); 4652 __ Bind(&done);
4698 } 4653 }
4699 4654
4700 4655
4701 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, 4656 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
4702 BranchInstr* branch) { 4657 BranchInstr* branch) {
4703 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); 4658 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
4704 Location left = locs()->in(0);
4705 Location right = locs()->in(1);
4706 if (left.IsConstant() && right.IsConstant()) {
4707 // TODO(vegorov): should be eliminated earlier by constant propagation.
4708 const bool result = (kind() == Token::kEQ_STRICT) ?
4709 left.constant().raw() == right.constant().raw() :
4710 left.constant().raw() != right.constant().raw();
4711 EmitBranchOnValue(compiler,
4712 branch->true_successor(),
4713 branch->false_successor(),
4714 result);
4715 return;
4716 }
4717 if (left.IsConstant()) {
4718 compiler->EmitEqualityRegConstCompare(right.reg(),
4719 left.constant(),
4720 needs_number_check(),
4721 token_pos());
4722 } else if (right.IsConstant()) {
4723 compiler->EmitEqualityRegConstCompare(left.reg(),
4724 right.constant(),
4725 needs_number_check(),
4726 token_pos());
4727 } else {
4728 compiler->EmitEqualityRegRegCompare(left.reg(),
4729 right.reg(),
4730 needs_number_check(),
4731 token_pos());
4732 }
4733 4659
4734 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; 4660 BranchLabels labels = CreateBranchLabels(compiler, branch);
4735 EmitBranchOnCondition(compiler, 4661
4736 branch->true_successor(), 4662 EmitStrictComparison(compiler, this, labels);
4737 branch->false_successor(),
4738 true_condition);
4739 } 4663 }
4740 4664
4741 4665
4742 // Detect pattern when one value is zero and another is a power of 2. 4666 // Detect pattern when one value is zero and another is a power of 2.
4743 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { 4667 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) {
4744 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || 4668 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) ||
4745 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); 4669 (Utils::IsPowerOfTwo(v2) && (v1 == 0));
4746 } 4670 }
4747 4671
4748 4672
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
4944 PcDescriptors::kOther, 4868 PcDescriptors::kOther,
4945 locs()); 4869 locs());
4946 __ Drop(2); // Discard type arguments and receiver. 4870 __ Drop(2); // Discard type arguments and receiver.
4947 } 4871 }
4948 4872
4949 } // namespace dart 4873 } // namespace dart
4950 4874
4951 #undef __ 4875 #undef __
4952 4876
4953 #endif // defined TARGET_ARCH_IA32 4877 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698