| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| 11 // with the distribution. | 11 // with the distribution. |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 } | 246 } |
| 247 } | 247 } |
| 248 return false; | 248 return false; |
| 249 } | 249 } |
| 250 | 250 |
| 251 | 251 |
| 252 bool HValue::Equals(HValue* other) const { | 252 bool HValue::Equals(HValue* other) const { |
| 253 if (other->opcode() != opcode()) return false; | 253 if (other->opcode() != opcode()) return false; |
| 254 if (!other->representation().Equals(representation())) return false; | 254 if (!other->representation().Equals(representation())) return false; |
| 255 if (!other->type_.Equals(type_)) return false; | 255 if (!other->type_.Equals(type_)) return false; |
| 256 if (other->flags() != flags()) return false; |
| 256 if (OperandCount() != other->OperandCount()) return false; | 257 if (OperandCount() != other->OperandCount()) return false; |
| 257 for (int i = 0; i < OperandCount(); ++i) { | 258 for (int i = 0; i < OperandCount(); ++i) { |
| 258 if (OperandAt(i)->id() != other->OperandAt(i)->id()) return false; | 259 if (OperandAt(i)->id() != other->OperandAt(i)->id()) return false; |
| 259 } | 260 } |
| 260 bool result = DataEquals(other); | 261 bool result = DataEquals(other); |
| 261 ASSERT(!result || Hashcode() == other->Hashcode()); | 262 ASSERT(!result || Hashcode() == other->Hashcode()); |
| 262 return result; | 263 return result; |
| 263 } | 264 } |
| 264 | 265 |
| 265 | 266 |
| 266 intptr_t HValue::Hashcode() const { | 267 intptr_t HValue::Hashcode() const { |
| 267 intptr_t result = opcode(); | 268 intptr_t result = opcode(); |
| 268 int count = OperandCount(); | 269 int count = OperandCount(); |
| 269 for (int i = 0; i < count; ++i) { | 270 for (int i = 0; i < count; ++i) { |
| 270 result = result * 19 + OperandAt(i)->id() + (result >> 7); | 271 result = result * 19 + OperandAt(i)->id() + (result >> 7); |
| 271 } | 272 } |
| 272 return result; | 273 return result; |
| 273 } | 274 } |
| 274 | 275 |
| 275 | 276 |
| 276 void HValue::SetOperandAt(int index, HValue* value) { | 277 void HValue::SetOperandAt(int index, HValue* value) { |
| 277 ASSERT(value == NULL || !value->representation().IsNone()); | 278 ASSERT(value == NULL || !value->representation().IsNone()); |
| 278 RegisterUse(index, value); | 279 RegisterUse(index, value); |
| 279 InternalSetOperandAt(index, value); | 280 InternalSetOperandAt(index, value); |
| 280 } | 281 } |
| 281 | 282 |
| 282 | 283 |
| 284 void HLoadKeyedGeneric::InternalSetOperandAt(int index, HValue* value) { |
| 285 if (index < 2) { |
| 286 operands_[index] = value; |
| 287 } else { |
| 288 context_ = value; |
| 289 } |
| 290 } |
| 291 |
| 292 |
| 293 void HStoreKeyedGeneric::InternalSetOperandAt(int index, HValue* value) { |
| 294 if (index < 3) { |
| 295 operands_[index] = value; |
| 296 } else { |
| 297 context_ = value; |
| 298 } |
| 299 } |
| 300 |
| 301 |
| 302 void HStoreNamedGeneric::InternalSetOperandAt(int index, HValue* value) { |
| 303 if (index < 2) { |
| 304 operands_[index] = value; |
| 305 } else { |
| 306 context_ = value; |
| 307 } |
| 308 } |
| 309 |
| 310 |
| 283 void HValue::ReplaceAndDelete(HValue* other) { | 311 void HValue::ReplaceAndDelete(HValue* other) { |
| 284 ReplaceValue(other); | 312 ReplaceValue(other); |
| 285 Delete(); | 313 Delete(); |
| 286 } | 314 } |
| 287 | 315 |
| 288 | 316 |
| 289 void HValue::ReplaceValue(HValue* other) { | 317 void HValue::ReplaceValue(HValue* other) { |
| 290 ZoneList<HValue*> start_uses(2); | 318 ZoneList<HValue*> start_uses(2); |
| 291 for (int i = 0; i < uses_.length(); ++i) { | 319 for (int i = 0; i < uses_.length(); ++i) { |
| 292 HValue* use = uses_.at(i); | 320 HValue* use = uses_.at(i); |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 | 458 |
| 431 if (representation().IsTagged() && !type().Equals(HType::Tagged())) { | 459 if (representation().IsTagged() && !type().Equals(HType::Tagged())) { |
| 432 stream->Add(" type[%s]", type().ToString()); | 460 stream->Add(" type[%s]", type().ToString()); |
| 433 } | 461 } |
| 434 } | 462 } |
| 435 | 463 |
| 436 | 464 |
| 437 void HInstruction::Unlink() { | 465 void HInstruction::Unlink() { |
| 438 ASSERT(IsLinked()); | 466 ASSERT(IsLinked()); |
| 439 ASSERT(!IsControlInstruction()); // Must never move control instructions. | 467 ASSERT(!IsControlInstruction()); // Must never move control instructions. |
| 468 ASSERT(!IsBlockEntry()); // Doesn't make sense to delete these. |
| 469 ASSERT(previous_ != NULL); |
| 470 previous_->next_ = next_; |
| 471 if (next_ == NULL) { |
| 472 ASSERT(block()->last() == this); |
| 473 block()->set_last(previous_); |
| 474 } else { |
| 475 next_->previous_ = previous_; |
| 476 } |
| 440 clear_block(); | 477 clear_block(); |
| 441 if (previous_ != NULL) previous_->next_ = next_; | |
| 442 if (next_ != NULL) next_->previous_ = previous_; | |
| 443 } | 478 } |
| 444 | 479 |
| 445 | 480 |
| 446 void HInstruction::InsertBefore(HInstruction* next) { | 481 void HInstruction::InsertBefore(HInstruction* next) { |
| 447 ASSERT(!IsLinked()); | 482 ASSERT(!IsLinked()); |
| 448 ASSERT(!next->IsBlockEntry()); | 483 ASSERT(!next->IsBlockEntry()); |
| 449 ASSERT(!IsControlInstruction()); | 484 ASSERT(!IsControlInstruction()); |
| 450 ASSERT(!next->block()->IsStartBlock()); | 485 ASSERT(!next->block()->IsStartBlock()); |
| 451 ASSERT(next->previous_ != NULL); | 486 ASSERT(next->previous_ != NULL); |
| 452 HInstruction* prev = next->previous(); | 487 HInstruction* prev = next->previous(); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 483 | 518 |
| 484 previous_ = previous; | 519 previous_ = previous; |
| 485 next_ = next; | 520 next_ = next; |
| 486 SetBlock(block); | 521 SetBlock(block); |
| 487 previous->next_ = this; | 522 previous->next_ = this; |
| 488 if (next != NULL) next->previous_ = this; | 523 if (next != NULL) next->previous_ = this; |
| 489 } | 524 } |
| 490 | 525 |
| 491 | 526 |
| 492 #ifdef DEBUG | 527 #ifdef DEBUG |
| 493 void HInstruction::Verify() const { | 528 void HInstruction::Verify() { |
| 494 // Verify that input operands are defined before use. | 529 // Verify that input operands are defined before use. |
| 495 HBasicBlock* cur_block = block(); | 530 HBasicBlock* cur_block = block(); |
| 496 for (int i = 0; i < OperandCount(); ++i) { | 531 for (int i = 0; i < OperandCount(); ++i) { |
| 497 HValue* other_operand = OperandAt(i); | 532 HValue* other_operand = OperandAt(i); |
| 498 HBasicBlock* other_block = other_operand->block(); | 533 HBasicBlock* other_block = other_operand->block(); |
| 499 if (cur_block == other_block) { | 534 if (cur_block == other_block) { |
| 500 if (!other_operand->IsPhi()) { | 535 if (!other_operand->IsPhi()) { |
| 501 HInstruction* cur = cur_block->first(); | 536 HInstruction* cur = cur_block->first(); |
| 502 while (cur != NULL) { | 537 while (cur != NULL) { |
| 503 ASSERT(cur != this); // We should reach other_operand before! | 538 ASSERT(cur != this); // We should reach other_operand before! |
| 504 if (cur == other_operand) break; | 539 if (cur == other_operand) break; |
| 505 cur = cur->next(); | 540 cur = cur->next(); |
| 506 } | 541 } |
| 507 // Must reach other operand in the same block! | 542 // Must reach other operand in the same block! |
| 508 ASSERT(cur == other_operand); | 543 ASSERT(cur == other_operand); |
| 509 } | 544 } |
| 510 } else { | 545 } else { |
| 511 ASSERT(other_block->Dominates(cur_block)); | 546 ASSERT(other_block->Dominates(cur_block)); |
| 512 } | 547 } |
| 513 } | 548 } |
| 514 | 549 |
| 515 // Verify that instructions that may have side-effects are followed | 550 // Verify that instructions that may have side-effects are followed |
| 516 // by a simulate instruction. | 551 // by a simulate instruction. |
| 517 if (HasSideEffects() && !IsOsrEntry()) { | 552 if (HasSideEffects() && !IsOsrEntry()) { |
| 518 ASSERT(next()->IsSimulate()); | 553 ASSERT(next()->IsSimulate()); |
| 519 } | 554 } |
| 555 |
| 556 // Verify that instructions that can be eliminated by GVN have overridden |
| 557 // HValue::DataEquals. The default implementation is UNREACHABLE. We |
| 558 // don't actually care whether DataEquals returns true or false here. |
| 559 if (CheckFlag(kUseGVN)) DataEquals(this); |
| 520 } | 560 } |
| 521 #endif | 561 #endif |
| 522 | 562 |
| 523 | 563 |
| 524 HCall::HCall(int count) : arguments_(Zone::NewArray<HValue*>(count), count) { | 564 void HCall::PrintDataTo(StringStream* stream) const { |
| 525 for (int i = 0; i < count; ++i) arguments_[i] = NULL; | 565 stream->Add("#%d", argument_count()); |
| 526 set_representation(Representation::Tagged()); | |
| 527 SetFlagMask(AllSideEffects()); | |
| 528 } | 566 } |
| 529 | 567 |
| 530 | 568 |
| 531 void HCall::PrintDataTo(StringStream* stream) const { | 569 void HUnaryCall::PrintDataTo(StringStream* stream) const { |
| 532 stream->Add("("); | 570 value()->PrintNameTo(stream); |
| 533 for (int i = 0; i < arguments_.length(); ++i) { | 571 stream->Add(" "); |
| 534 if (i != 0) stream->Add(", "); | 572 HCall::PrintDataTo(stream); |
| 535 arguments_.at(i)->PrintNameTo(stream); | 573 } |
| 574 |
| 575 |
| 576 void HBinaryCall::PrintDataTo(StringStream* stream) const { |
| 577 first()->PrintNameTo(stream); |
| 578 stream->Add(" "); |
| 579 second()->PrintNameTo(stream); |
| 580 stream->Add(" "); |
| 581 HCall::PrintDataTo(stream); |
| 582 } |
| 583 |
| 584 |
| 585 void HCallConstantFunction::PrintDataTo(StringStream* stream) const { |
| 586 if (IsApplyFunction()) { |
| 587 stream->Add("optimized apply "); |
| 588 } else { |
| 589 stream->Add("%o ", function()->shared()->DebugName()); |
| 536 } | 590 } |
| 537 stream->Add(")"); | 591 HCall::PrintDataTo(stream); |
| 592 } |
| 593 |
| 594 |
| 595 void HCallNamed::PrintDataTo(StringStream* stream) const { |
| 596 stream->Add("%o ", *name()); |
| 597 HUnaryCall::PrintDataTo(stream); |
| 598 } |
| 599 |
| 600 |
| 601 void HCallGlobal::PrintDataTo(StringStream* stream) const { |
| 602 stream->Add("%o ", *name()); |
| 603 HUnaryCall::PrintDataTo(stream); |
| 604 } |
| 605 |
| 606 |
| 607 void HCallKnownGlobal::PrintDataTo(StringStream* stream) const { |
| 608 stream->Add("o ", target()->shared()->DebugName()); |
| 609 HCall::PrintDataTo(stream); |
| 610 } |
| 611 |
| 612 |
| 613 void HCallRuntime::PrintDataTo(StringStream* stream) const { |
| 614 stream->Add("%o ", *name()); |
| 615 HCall::PrintDataTo(stream); |
| 538 } | 616 } |
| 539 | 617 |
| 540 | 618 |
| 541 void HClassOfTest::PrintDataTo(StringStream* stream) const { | 619 void HClassOfTest::PrintDataTo(StringStream* stream) const { |
| 542 stream->Add("class_of_test("); | 620 stream->Add("class_of_test("); |
| 543 value()->PrintTo(stream); | 621 value()->PrintNameTo(stream); |
| 544 stream->Add(", \"%o\")", *class_name()); | 622 stream->Add(", \"%o\")", *class_name()); |
| 545 } | 623 } |
| 546 | 624 |
| 547 | 625 |
| 548 void HAccessArgumentsAt::PrintDataTo(StringStream* stream) const { | 626 void HAccessArgumentsAt::PrintDataTo(StringStream* stream) const { |
| 549 arguments()->PrintNameTo(stream); | 627 arguments()->PrintNameTo(stream); |
| 550 stream->Add("["); | 628 stream->Add("["); |
| 551 index()->PrintNameTo(stream); | 629 index()->PrintNameTo(stream); |
| 552 stream->Add("], length "); | 630 stream->Add("], length "); |
| 553 length()->PrintNameTo(stream); | 631 length()->PrintNameTo(stream); |
| 554 } | 632 } |
| 555 | 633 |
| 556 | 634 |
| 557 void HCall::SetArgumentAt(int index, HPushArgument* push_argument) { | 635 void HControlInstruction::PrintDataTo(StringStream* stream) const { |
| 558 push_argument->set_argument_index(index); | 636 if (FirstSuccessor() != NULL) { |
| 559 SetOperandAt(index, push_argument); | 637 int first_id = FirstSuccessor()->block_id(); |
| 638 if (SecondSuccessor() == NULL) { |
| 639 stream->Add(" B%d", first_id); |
| 640 } else { |
| 641 int second_id = SecondSuccessor()->block_id(); |
| 642 stream->Add(" goto (B%d, B%d)", first_id, second_id); |
| 643 } |
| 644 } |
| 560 } | 645 } |
| 561 | 646 |
| 562 | 647 |
| 563 void HCallConstantFunction::PrintDataTo(StringStream* stream) const { | 648 void HUnaryControlInstruction::PrintDataTo(StringStream* stream) const { |
| 564 if (IsApplyFunction()) { | 649 value()->PrintNameTo(stream); |
| 565 stream->Add("SPECIAL function: apply"); | 650 HControlInstruction::PrintDataTo(stream); |
| 566 } else { | |
| 567 stream->Add("%s", *(function()->shared()->DebugName()->ToCString())); | |
| 568 } | |
| 569 HCall::PrintDataTo(stream); | |
| 570 } | 651 } |
| 571 | 652 |
| 572 | 653 |
| 573 void HBranch::PrintDataTo(StringStream* stream) const { | 654 void HCompareMap::PrintDataTo(StringStream* stream) const { |
| 574 int first_id = FirstSuccessor()->block_id(); | |
| 575 int second_id = SecondSuccessor()->block_id(); | |
| 576 stream->Add("on "); | |
| 577 value()->PrintNameTo(stream); | 655 value()->PrintNameTo(stream); |
| 578 stream->Add(" (B%d, B%d)", first_id, second_id); | 656 stream->Add(" (%p)", *map()); |
| 657 HControlInstruction::PrintDataTo(stream); |
| 579 } | 658 } |
| 580 | 659 |
| 581 | 660 |
| 582 void HCompareMapAndBranch::PrintDataTo(StringStream* stream) const { | |
| 583 stream->Add("on "); | |
| 584 value()->PrintNameTo(stream); | |
| 585 stream->Add(" (%p)", *map()); | |
| 586 } | |
| 587 | |
| 588 | |
| 589 void HGoto::PrintDataTo(StringStream* stream) const { | |
| 590 stream->Add("B%d", FirstSuccessor()->block_id()); | |
| 591 } | |
| 592 | |
| 593 | |
| 594 void HReturn::PrintDataTo(StringStream* stream) const { | |
| 595 value()->PrintNameTo(stream); | |
| 596 } | |
| 597 | |
| 598 | |
| 599 void HThrow::PrintDataTo(StringStream* stream) const { | |
| 600 value()->PrintNameTo(stream); | |
| 601 } | |
| 602 | |
| 603 | |
| 604 const char* HUnaryMathOperation::OpName() const { | 661 const char* HUnaryMathOperation::OpName() const { |
| 605 switch (op()) { | 662 switch (op()) { |
| 606 case kMathFloor: return "floor"; | 663 case kMathFloor: return "floor"; |
| 607 case kMathRound: return "round"; | 664 case kMathRound: return "round"; |
| 608 case kMathCeil: return "ceil"; | 665 case kMathCeil: return "ceil"; |
| 609 case kMathAbs: return "abs"; | 666 case kMathAbs: return "abs"; |
| 610 case kMathLog: return "log"; | 667 case kMathLog: return "log"; |
| 611 case kMathSin: return "sin"; | 668 case kMathSin: return "sin"; |
| 612 case kMathCos: return "cos"; | 669 case kMathCos: return "cos"; |
| 613 case kMathTan: return "tan"; | 670 case kMathTan: return "tan"; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 655 } | 712 } |
| 656 | 713 |
| 657 | 714 |
| 658 void HTypeofIs::PrintDataTo(StringStream* stream) const { | 715 void HTypeofIs::PrintDataTo(StringStream* stream) const { |
| 659 value()->PrintNameTo(stream); | 716 value()->PrintNameTo(stream); |
| 660 stream->Add(" == "); | 717 stream->Add(" == "); |
| 661 stream->Add(type_literal_->ToAsciiVector()); | 718 stream->Add(type_literal_->ToAsciiVector()); |
| 662 } | 719 } |
| 663 | 720 |
| 664 | 721 |
| 665 void HPushArgument::PrintDataTo(StringStream* stream) const { | |
| 666 HUnaryOperation::PrintDataTo(stream); | |
| 667 if (argument_index() != -1) { | |
| 668 stream->Add(" [%d]", argument_index_); | |
| 669 } | |
| 670 } | |
| 671 | |
| 672 | |
| 673 void HChange::PrintDataTo(StringStream* stream) const { | 722 void HChange::PrintDataTo(StringStream* stream) const { |
| 674 HUnaryOperation::PrintDataTo(stream); | 723 HUnaryOperation::PrintDataTo(stream); |
| 675 stream->Add(" %s to %s", from_.Mnemonic(), to_.Mnemonic()); | 724 stream->Add(" %s to %s", from_.Mnemonic(), to_.Mnemonic()); |
| 676 | 725 |
| 677 if (CanTruncateToInt32()) stream->Add(" truncating-int32"); | 726 if (CanTruncateToInt32()) stream->Add(" truncating-int32"); |
| 678 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?"); | 727 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?"); |
| 679 } | 728 } |
| 680 | 729 |
| 681 | 730 |
| 682 HCheckInstanceType* HCheckInstanceType::NewIsJSObjectOrJSFunction( | 731 HCheckInstanceType* HCheckInstanceType::NewIsJSObjectOrJSFunction( |
| 683 HValue* value) { | 732 HValue* value) { |
| 684 STATIC_ASSERT((LAST_JS_OBJECT_TYPE + 1) == JS_FUNCTION_TYPE); | 733 STATIC_ASSERT((LAST_JS_OBJECT_TYPE + 1) == JS_FUNCTION_TYPE); |
| 685 return new HCheckInstanceType(value, FIRST_JS_OBJECT_TYPE, JS_FUNCTION_TYPE); | 734 return new HCheckInstanceType(value, FIRST_JS_OBJECT_TYPE, JS_FUNCTION_TYPE); |
| 686 } | 735 } |
| 687 | 736 |
| 688 | 737 |
| 689 void HCheckMap::PrintDataTo(StringStream* stream) const { | 738 void HCheckMap::PrintDataTo(StringStream* stream) const { |
| 690 value()->PrintNameTo(stream); | 739 value()->PrintNameTo(stream); |
| 691 stream->Add(" %p", *map()); | 740 stream->Add(" %p", *map()); |
| 692 } | 741 } |
| 693 | 742 |
| 694 | 743 |
| 695 void HCheckFunction::PrintDataTo(StringStream* stream) const { | 744 void HCheckFunction::PrintDataTo(StringStream* stream) const { |
| 696 value()->PrintNameTo(stream); | 745 value()->PrintNameTo(stream); |
| 697 stream->Add(" %p", *target()); | 746 stream->Add(" %p", *target()); |
| 698 } | 747 } |
| 699 | 748 |
| 700 | 749 |
| 701 void HCallKeyed::PrintDataTo(StringStream* stream) const { | 750 void HCallStub::PrintDataTo(StringStream* stream) const { |
| 702 stream->Add("["); | 751 stream->Add("%s ", |
| 703 key()->PrintNameTo(stream); | 752 CodeStub::MajorName(major_key_, false)); |
| 704 stream->Add("]("); | 753 HUnaryCall::PrintDataTo(stream); |
| 705 for (int i = 1; i < arguments_.length(); ++i) { | |
| 706 if (i != 1) stream->Add(", "); | |
| 707 arguments_.at(i)->PrintNameTo(stream); | |
| 708 } | |
| 709 stream->Add(")"); | |
| 710 } | 754 } |
| 711 | 755 |
| 712 | 756 |
| 713 void HCallNamed::PrintDataTo(StringStream* stream) const { | 757 void HInstanceOf::PrintDataTo(StringStream* stream) const { |
| 714 SmartPointer<char> name_string = name()->ToCString(); | 758 left()->PrintNameTo(stream); |
| 715 stream->Add("%s ", *name_string); | 759 stream->Add(" "); |
| 716 HCall::PrintDataTo(stream); | 760 right()->PrintNameTo(stream); |
| 717 } | 761 stream->Add(" "); |
| 718 | 762 context()->PrintNameTo(stream); |
| 719 | |
| 720 void HCallGlobal::PrintDataTo(StringStream* stream) const { | |
| 721 SmartPointer<char> name_string = name()->ToCString(); | |
| 722 stream->Add("%s ", *name_string); | |
| 723 HCall::PrintDataTo(stream); | |
| 724 } | |
| 725 | |
| 726 | |
| 727 void HCallRuntime::PrintDataTo(StringStream* stream) const { | |
| 728 SmartPointer<char> name_string = name()->ToCString(); | |
| 729 stream->Add("%s ", *name_string); | |
| 730 HCall::PrintDataTo(stream); | |
| 731 } | |
| 732 | |
| 733 void HCallStub::PrintDataTo(StringStream* stream) const { | |
| 734 stream->Add("%s(%d)", | |
| 735 CodeStub::MajorName(major_key_, false), | |
| 736 argument_count_); | |
| 737 } | 763 } |
| 738 | 764 |
| 739 | 765 |
| 740 Range* HValue::InferRange() { | 766 Range* HValue::InferRange() { |
| 741 if (representation().IsTagged()) { | 767 if (representation().IsTagged()) { |
| 742 // Tagged values are always in int32 range when converted to integer, | 768 // Tagged values are always in int32 range when converted to integer, |
| 743 // but they can contain -0. | 769 // but they can contain -0. |
| 744 Range* result = new Range(); | 770 Range* result = new Range(); |
| 745 result->set_can_be_minus_zero(true); | 771 result->set_can_be_minus_zero(true); |
| 746 return result; | 772 return result; |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 892 void HPhi::AddInput(HValue* value) { | 918 void HPhi::AddInput(HValue* value) { |
| 893 inputs_.Add(NULL); | 919 inputs_.Add(NULL); |
| 894 SetOperandAt(OperandCount() - 1, value); | 920 SetOperandAt(OperandCount() - 1, value); |
| 895 // Mark phis that may have 'arguments' directly or indirectly as an operand. | 921 // Mark phis that may have 'arguments' directly or indirectly as an operand. |
| 896 if (!CheckFlag(kIsArguments) && value->CheckFlag(kIsArguments)) { | 922 if (!CheckFlag(kIsArguments) && value->CheckFlag(kIsArguments)) { |
| 897 SetFlag(kIsArguments); | 923 SetFlag(kIsArguments); |
| 898 } | 924 } |
| 899 } | 925 } |
| 900 | 926 |
| 901 | 927 |
| 902 bool HPhi::HasReceiverOperand() { | |
| 903 for (int i = 0; i < OperandCount(); i++) { | |
| 904 if (OperandAt(i)->IsParameter() && | |
| 905 HParameter::cast(OperandAt(i))->index() == 0) { | |
| 906 return true; | |
| 907 } | |
| 908 } | |
| 909 return false; | |
| 910 } | |
| 911 | |
| 912 | |
| 913 HValue* HPhi::GetRedundantReplacement() const { | 928 HValue* HPhi::GetRedundantReplacement() const { |
| 914 HValue* candidate = NULL; | 929 HValue* candidate = NULL; |
| 915 int count = OperandCount(); | 930 int count = OperandCount(); |
| 916 int position = 0; | 931 int position = 0; |
| 917 while (position < count && candidate == NULL) { | 932 while (position < count && candidate == NULL) { |
| 918 HValue* current = OperandAt(position++); | 933 HValue* current = OperandAt(position++); |
| 919 if (current != this) candidate = current; | 934 if (current != this) candidate = current; |
| 920 } | 935 } |
| 921 while (position < count) { | 936 while (position < count) { |
| 922 HValue* current = OperandAt(position++); | 937 HValue* current = OperandAt(position++); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 989 : handle_(handle), | 1004 : handle_(handle), |
| 990 constant_type_(HType::TypeFromValue(handle)), | 1005 constant_type_(HType::TypeFromValue(handle)), |
| 991 has_int32_value_(false), | 1006 has_int32_value_(false), |
| 992 int32_value_(0), | 1007 int32_value_(0), |
| 993 has_double_value_(false), | 1008 has_double_value_(false), |
| 994 double_value_(0) { | 1009 double_value_(0) { |
| 995 set_representation(r); | 1010 set_representation(r); |
| 996 SetFlag(kUseGVN); | 1011 SetFlag(kUseGVN); |
| 997 if (handle_->IsNumber()) { | 1012 if (handle_->IsNumber()) { |
| 998 double n = handle_->Number(); | 1013 double n = handle_->Number(); |
| 999 has_int32_value_ = static_cast<double>(static_cast<int32_t>(n)) == n; | 1014 double roundtrip_value = static_cast<double>(static_cast<int32_t>(n)); |
| 1015 has_int32_value_ = BitCast<int64_t>(roundtrip_value) == BitCast<int64_t>(n); |
| 1000 if (has_int32_value_) int32_value_ = static_cast<int32_t>(n); | 1016 if (has_int32_value_) int32_value_ = static_cast<int32_t>(n); |
| 1001 double_value_ = n; | 1017 double_value_ = n; |
| 1002 has_double_value_ = true; | 1018 has_double_value_ = true; |
| 1003 } | 1019 } |
| 1004 } | 1020 } |
| 1005 | 1021 |
| 1006 | 1022 |
| 1007 HConstant* HConstant::CopyToRepresentation(Representation r) const { | 1023 HConstant* HConstant::CopyToRepresentation(Representation r) const { |
| 1008 if (r.IsInteger32() && !has_int32_value_) return NULL; | 1024 if (r.IsInteger32() && !has_int32_value_) return NULL; |
| 1009 if (r.IsDouble() && !has_double_value_) return NULL; | 1025 if (r.IsDouble() && !has_double_value_) return NULL; |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1116 void HCompare::PrintDataTo(StringStream* stream) const { | 1132 void HCompare::PrintDataTo(StringStream* stream) const { |
| 1117 stream->Add(Token::Name(token())); | 1133 stream->Add(Token::Name(token())); |
| 1118 stream->Add(" "); | 1134 stream->Add(" "); |
| 1119 HBinaryOperation::PrintDataTo(stream); | 1135 HBinaryOperation::PrintDataTo(stream); |
| 1120 } | 1136 } |
| 1121 | 1137 |
| 1122 | 1138 |
| 1123 void HCompare::SetInputRepresentation(Representation r) { | 1139 void HCompare::SetInputRepresentation(Representation r) { |
| 1124 input_representation_ = r; | 1140 input_representation_ = r; |
| 1125 if (r.IsTagged()) { | 1141 if (r.IsTagged()) { |
| 1126 SetFlagMask(AllSideEffects()); | 1142 SetAllSideEffects(); |
| 1127 ClearFlag(kUseGVN); | 1143 ClearFlag(kUseGVN); |
| 1128 } else { | 1144 } else { |
| 1129 ClearFlagMask(AllSideEffects()); | 1145 ClearAllSideEffects(); |
| 1130 SetFlag(kUseGVN); | 1146 SetFlag(kUseGVN); |
| 1131 } | 1147 } |
| 1132 } | 1148 } |
| 1133 | 1149 |
| 1134 | 1150 |
| 1135 void HParameter::PrintDataTo(StringStream* stream) const { | 1151 void HParameter::PrintDataTo(StringStream* stream) const { |
| 1136 stream->Add("%u", index()); | 1152 stream->Add("%u", index()); |
| 1137 } | 1153 } |
| 1138 | 1154 |
| 1139 | 1155 |
| 1140 void HLoadNamedField::PrintDataTo(StringStream* stream) const { | 1156 void HLoadNamedField::PrintDataTo(StringStream* stream) const { |
| 1141 object()->PrintNameTo(stream); | 1157 object()->PrintNameTo(stream); |
| 1142 stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : ""); | 1158 stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : ""); |
| 1143 } | 1159 } |
| 1144 | 1160 |
| 1145 | 1161 |
| 1146 void HLoadKeyed::PrintDataTo(StringStream* stream) const { | 1162 void HLoadKeyed::PrintDataTo(StringStream* stream) const { |
| 1147 object()->PrintNameTo(stream); | 1163 object()->PrintNameTo(stream); |
| 1148 stream->Add("["); | 1164 stream->Add("["); |
| 1149 key()->PrintNameTo(stream); | 1165 key()->PrintNameTo(stream); |
| 1150 stream->Add("]"); | 1166 stream->Add("]"); |
| 1151 } | 1167 } |
| 1152 | 1168 |
| 1153 | 1169 |
| 1170 void HLoadPixelArrayElement::PrintDataTo(StringStream* stream) const { |
| 1171 external_pointer()->PrintNameTo(stream); |
| 1172 stream->Add("["); |
| 1173 key()->PrintNameTo(stream); |
| 1174 stream->Add("]"); |
| 1175 } |
| 1176 |
| 1177 |
| 1154 void HStoreNamed::PrintDataTo(StringStream* stream) const { | 1178 void HStoreNamed::PrintDataTo(StringStream* stream) const { |
| 1155 object()->PrintNameTo(stream); | 1179 object()->PrintNameTo(stream); |
| 1156 stream->Add("."); | 1180 stream->Add("."); |
| 1157 ASSERT(name()->IsString()); | 1181 ASSERT(name()->IsString()); |
| 1158 stream->Add(*String::cast(*name())->ToCString()); | 1182 stream->Add(*String::cast(*name())->ToCString()); |
| 1159 stream->Add(" = "); | 1183 stream->Add(" = "); |
| 1160 value()->PrintNameTo(stream); | 1184 value()->PrintNameTo(stream); |
| 1161 } | 1185 } |
| 1162 | 1186 |
| 1163 | 1187 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1183 if (check_hole_value()) stream->Add(" (deleteable/read-only)"); | 1207 if (check_hole_value()) stream->Add(" (deleteable/read-only)"); |
| 1184 } | 1208 } |
| 1185 | 1209 |
| 1186 | 1210 |
| 1187 void HStoreGlobal::PrintDataTo(StringStream* stream) const { | 1211 void HStoreGlobal::PrintDataTo(StringStream* stream) const { |
| 1188 stream->Add("[%p] = ", *cell()); | 1212 stream->Add("[%p] = ", *cell()); |
| 1189 value()->PrintNameTo(stream); | 1213 value()->PrintNameTo(stream); |
| 1190 } | 1214 } |
| 1191 | 1215 |
| 1192 | 1216 |
| 1217 void HLoadContextSlot::PrintDataTo(StringStream* stream) const { |
| 1218 value()->PrintNameTo(stream); |
| 1219 stream->Add("[%d]", slot_index()); |
| 1220 } |
| 1221 |
| 1222 |
| 1223 void HStoreContextSlot::PrintDataTo(StringStream* stream) const { |
| 1224 context()->PrintNameTo(stream); |
| 1225 stream->Add("[%d] = ", slot_index()); |
| 1226 value()->PrintNameTo(stream); |
| 1227 } |
| 1228 |
| 1229 |
| 1193 // Implementation of type inference and type conversions. Calculates | 1230 // Implementation of type inference and type conversions. Calculates |
| 1194 // the inferred type of this instruction based on the input operands. | 1231 // the inferred type of this instruction based on the input operands. |
| 1195 | 1232 |
| 1196 HType HValue::CalculateInferredType() const { | 1233 HType HValue::CalculateInferredType() const { |
| 1197 return type_; | 1234 return type_; |
| 1198 } | 1235 } |
| 1199 | 1236 |
| 1200 | 1237 |
| 1201 HType HCheckMap::CalculateInferredType() const { | 1238 HType HCheckMap::CalculateInferredType() const { |
| 1202 return value()->type(); | 1239 return value()->type(); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1242 HType HCompareJSObjectEq::CalculateInferredType() const { | 1279 HType HCompareJSObjectEq::CalculateInferredType() const { |
| 1243 return HType::Boolean(); | 1280 return HType::Boolean(); |
| 1244 } | 1281 } |
| 1245 | 1282 |
| 1246 | 1283 |
| 1247 HType HUnaryPredicate::CalculateInferredType() const { | 1284 HType HUnaryPredicate::CalculateInferredType() const { |
| 1248 return HType::Boolean(); | 1285 return HType::Boolean(); |
| 1249 } | 1286 } |
| 1250 | 1287 |
| 1251 | 1288 |
| 1289 HType HBitwiseBinaryOperation::CalculateInferredType() const { |
| 1290 return HType::TaggedNumber(); |
| 1291 } |
| 1292 |
| 1293 |
| 1252 HType HArithmeticBinaryOperation::CalculateInferredType() const { | 1294 HType HArithmeticBinaryOperation::CalculateInferredType() const { |
| 1253 return HType::TaggedNumber(); | 1295 return HType::TaggedNumber(); |
| 1254 } | 1296 } |
| 1255 | 1297 |
| 1256 | 1298 |
| 1257 HType HAdd::CalculateInferredType() const { | 1299 HType HAdd::CalculateInferredType() const { |
| 1258 return HType::Tagged(); | 1300 return HType::Tagged(); |
| 1259 } | 1301 } |
| 1260 | 1302 |
| 1261 | 1303 |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1375 if (range() == NULL || range()->CanBeMinusZero()) { | 1417 if (range() == NULL || range()->CanBeMinusZero()) { |
| 1376 return left(); | 1418 return left(); |
| 1377 } | 1419 } |
| 1378 return NULL; | 1420 return NULL; |
| 1379 } | 1421 } |
| 1380 | 1422 |
| 1381 | 1423 |
| 1382 // Node-specific verification code is only included in debug mode. | 1424 // Node-specific verification code is only included in debug mode. |
| 1383 #ifdef DEBUG | 1425 #ifdef DEBUG |
| 1384 | 1426 |
| 1385 void HPhi::Verify() const { | 1427 void HPhi::Verify() { |
| 1386 ASSERT(OperandCount() == block()->predecessors()->length()); | 1428 ASSERT(OperandCount() == block()->predecessors()->length()); |
| 1387 for (int i = 0; i < OperandCount(); ++i) { | 1429 for (int i = 0; i < OperandCount(); ++i) { |
| 1388 HValue* value = OperandAt(i); | 1430 HValue* value = OperandAt(i); |
| 1389 HBasicBlock* defining_block = value->block(); | 1431 HBasicBlock* defining_block = value->block(); |
| 1390 HBasicBlock* predecessor_block = block()->predecessors()->at(i); | 1432 HBasicBlock* predecessor_block = block()->predecessors()->at(i); |
| 1391 ASSERT(defining_block == predecessor_block || | 1433 ASSERT(defining_block == predecessor_block || |
| 1392 defining_block->Dominates(predecessor_block)); | 1434 defining_block->Dominates(predecessor_block)); |
| 1393 } | 1435 } |
| 1394 } | 1436 } |
| 1395 | 1437 |
| 1396 | 1438 |
| 1397 void HSimulate::Verify() const { | 1439 void HSimulate::Verify() { |
| 1398 HInstruction::Verify(); | 1440 HInstruction::Verify(); |
| 1399 ASSERT(HasAstId()); | 1441 ASSERT(HasAstId()); |
| 1400 } | 1442 } |
| 1401 | 1443 |
| 1402 | 1444 |
| 1403 void HBoundsCheck::Verify() const { | 1445 void HBoundsCheck::Verify() { |
| 1404 HInstruction::Verify(); | 1446 HInstruction::Verify(); |
| 1405 ASSERT(HasNoUses()); | 1447 ASSERT(HasNoUses()); |
| 1406 } | 1448 } |
| 1407 | 1449 |
| 1408 | 1450 |
| 1409 void HCheckSmi::Verify() const { | 1451 void HCheckSmi::Verify() { |
| 1410 HInstruction::Verify(); | 1452 HInstruction::Verify(); |
| 1411 ASSERT(HasNoUses()); | 1453 ASSERT(HasNoUses()); |
| 1412 } | 1454 } |
| 1413 | 1455 |
| 1414 | 1456 |
| 1415 void HCheckNonSmi::Verify() const { | 1457 void HCheckNonSmi::Verify() { |
| 1416 HInstruction::Verify(); | 1458 HInstruction::Verify(); |
| 1417 ASSERT(HasNoUses()); | 1459 ASSERT(HasNoUses()); |
| 1418 } | 1460 } |
| 1419 | 1461 |
| 1420 | 1462 |
| 1421 void HCheckInstanceType::Verify() const { | 1463 void HCheckInstanceType::Verify() { |
| 1422 HInstruction::Verify(); | 1464 HInstruction::Verify(); |
| 1423 ASSERT(HasNoUses()); | 1465 ASSERT(HasNoUses()); |
| 1424 } | 1466 } |
| 1425 | 1467 |
| 1426 | 1468 |
| 1427 void HCheckMap::Verify() const { | 1469 void HCheckMap::Verify() { |
| 1428 HInstruction::Verify(); | 1470 HInstruction::Verify(); |
| 1429 ASSERT(HasNoUses()); | 1471 ASSERT(HasNoUses()); |
| 1430 } | 1472 } |
| 1431 | 1473 |
| 1432 | 1474 |
| 1433 void HCheckFunction::Verify() const { | 1475 void HCheckFunction::Verify() { |
| 1434 HInstruction::Verify(); | 1476 HInstruction::Verify(); |
| 1435 ASSERT(HasNoUses()); | 1477 ASSERT(HasNoUses()); |
| 1436 } | 1478 } |
| 1437 | 1479 |
| 1438 | 1480 |
| 1439 void HCheckPrototypeMaps::Verify() const { | 1481 void HCheckPrototypeMaps::Verify() { |
| 1440 HInstruction::Verify(); | 1482 HInstruction::Verify(); |
| 1441 ASSERT(HasNoUses()); | 1483 ASSERT(HasNoUses()); |
| 1442 } | 1484 } |
| 1443 | 1485 |
| 1444 #endif | 1486 #endif |
| 1445 | 1487 |
| 1446 } } // namespace v8::internal | 1488 } } // namespace v8::internal |
| OLD | NEW |