1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #ifndef V8_HYDROGEN_INSTRUCTIONS_H_ 29 #define V8_HYDROGEN_INSTRUCTIONS_H_ 30 31 #include "v8.h" 32 33 #include "allocation.h" 34 #include "code-stubs.h" 35 #include "data-flow.h" 36 #include "small-pointer-list.h" 37 #include "string-stream.h" 38 #include "v8conversions.h" 39 #include "v8utils.h" 40 #include "zone.h" 41 42 namespace v8 { 43 namespace internal { 44 45 // Forward declarations. 46 class HBasicBlock; 47 class HEnvironment; 48 class HInstruction; 49 class HLoopInformation; 50 class HValue; 51 class LInstruction; 52 class LChunkBuilder; 53 54 55 #define HYDROGEN_ABSTRACT_INSTRUCTION_LIST(V) \ 56 V(BitwiseBinaryOperation) \ 57 V(ControlInstruction) \ 58 V(Instruction) \ 59 60 61 #define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \ 62 V(AbnormalExit) \ 63 V(AccessArgumentsAt) \ 64 V(Add) \ 65 V(AllocateObject) \ 66 V(ApplyArguments) \ 67 V(ArgumentsElements) \ 68 V(ArgumentsLength) \ 69 V(ArgumentsObject) \ 70 V(ArrayLiteral) \ 71 V(Bitwise) \ 72 V(BitNot) \ 73 V(BlockEntry) \ 74 V(BoundsCheck) \ 75 V(Branch) \ 76 V(CallConstantFunction) \ 77 V(CallFunction) \ 78 V(CallGlobal) \ 79 V(CallKeyed) \ 80 V(CallKnownGlobal) \ 81 V(CallNamed) \ 82 V(CallNew) \ 83 V(CallRuntime) \ 84 V(CallStub) \ 85 V(Change) \ 86 V(CheckFunction) \ 87 V(CheckInstanceType) \ 88 V(CheckMap) \ 89 V(CheckNonSmi) \ 90 V(CheckPrototypeMaps) \ 91 V(CheckSmi) \ 92 V(ClampToUint8) \ 93 V(ClassOfTestAndBranch) \ 94 V(CompareIDAndBranch) \ 95 V(CompareGeneric) \ 96 V(CompareObjectEqAndBranch) \ 97 V(CompareMap) \ 98 V(CompareConstantEqAndBranch) \ 99 V(Constant) \ 100 V(Context) \ 101 V(DeclareGlobals) \ 102 V(DeleteProperty) \ 103 V(Deoptimize) \ 104 V(Div) \ 105 V(ElementsKind) \ 106 V(EnterInlined) \ 107 V(FastLiteral) \ 108 V(FixedArrayBaseLength) \ 109 V(ForceRepresentation) \ 110 V(FunctionLiteral) \ 111 V(GetCachedArrayIndex) \ 112 V(GlobalObject) \ 113 V(GlobalReceiver) \ 114 V(Goto) \ 115 V(HasCachedArrayIndexAndBranch) \ 116 V(HasInstanceTypeAndBranch) \ 117 V(In) \ 118 V(InstanceOf) \ 119 V(InstanceOfKnownGlobal) \ 120 V(InvokeFunction) \ 121 V(IsConstructCallAndBranch) \ 122 V(IsNilAndBranch) \ 123 V(IsObjectAndBranch) \ 124 V(IsStringAndBranch) \ 125 V(IsSmiAndBranch) \ 126 V(IsUndetectableAndBranch) \ 127 V(StringCompareAndBranch) \ 128 V(JSArrayLength) \ 129 V(LeaveInlined) \ 130 V(LoadContextSlot) \ 131 V(LoadElements) \ 132 V(LoadExternalArrayPointer) \ 133 V(LoadFunctionPrototype) \ 134 V(LoadGlobalCell) \ 135 V(LoadGlobalGeneric) \ 136 V(LoadKeyedFastDoubleElement) \ 137 V(LoadKeyedFastElement) \ 138 V(LoadKeyedGeneric) \ 139 V(LoadKeyedSpecializedArrayElement) \ 140 V(LoadNamedField) \ 141 V(LoadNamedFieldPolymorphic) \ 142 V(LoadNamedGeneric) \ 143 V(Mod) \ 144 V(Mul) \ 145 V(ObjectLiteral) \ 146 V(OsrEntry) \ 147 V(OuterContext) \ 148 V(Parameter) \ 149 V(Power) \ 150 V(PushArgument) \ 151 V(Random) \ 152 V(RegExpLiteral) \ 153 V(Return) \ 154 V(Sar) \ 155 V(Shl) \ 156 V(Shr) \ 157 V(Simulate) \ 158 V(SoftDeoptimize) \ 159 V(StackCheck) \ 160 V(StoreContextSlot) \ 161 V(StoreGlobalCell) \ 162 V(StoreGlobalGeneric) \ 163 V(StoreKeyedFastDoubleElement) \ 164 V(StoreKeyedFastElement) \ 165 V(StoreKeyedGeneric) \ 166 V(StoreKeyedSpecializedArrayElement) \ 167 V(StoreNamedField) \ 168 V(StoreNamedGeneric) \ 169 V(StringAdd) \ 170 V(StringCharCodeAt) \ 171 V(StringCharFromCode) \ 172 V(StringLength) \ 173 V(Sub) \ 174 V(ThisFunction) \ 175 V(Throw) \ 176 V(ToFastProperties) \ 177 V(TransitionElementsKind) \ 178 V(Typeof) \ 179 V(TypeofIsAndBranch) \ 180 V(UnaryMathOperation) \ 181 V(UnknownOSRValue) \ 182 V(UseConst) \ 183 V(ValueOf) \ 184 V(ForInPrepareMap) \ 185 V(ForInCacheArray) \ 186 V(CheckMapValue) \ 187 V(LoadFieldByIndex) \ 188 V(DateField) \ 189 V(WrapReceiver) 190 191 #define GVN_FLAG_LIST(V) \ 192 V(Calls) \ 193 V(InobjectFields) \ 194 V(BackingStoreFields) \ 195 V(ElementsKind) \ 196 V(ElementsPointer) \ 197 V(ArrayElements) \ 198 V(DoubleArrayElements) \ 199 V(SpecializedArrayElements) \ 200 V(GlobalVars) \ 201 V(Maps) \ 202 V(ArrayLengths) \ 203 V(ContextSlots) \ 204 V(OsrEntries) 205 206 #define DECLARE_ABSTRACT_INSTRUCTION(type) \ 207 virtual bool Is##type() const { return true; } \ 208 static H##type* cast(HValue* value) { \ 209 ASSERT(value->Is##type()); \ 210 return reinterpret_cast<H##type*>(value); \ 211 } 212 213 214 #define DECLARE_CONCRETE_INSTRUCTION(type) \ 215 virtual LInstruction* CompileToLithium(LChunkBuilder* builder); \ 216 static H##type* cast(HValue* value) { \ 217 ASSERT(value->Is##type()); \ 218 return reinterpret_cast<H##type*>(value); \ 219 } \ 220 virtual Opcode opcode() const { return HValue::k##type; } 221 222 223 class Range: public ZoneObject { 224 public: 225 Range() 226 : lower_(kMinInt), 227 upper_(kMaxInt), 228 next_(NULL), 229 can_be_minus_zero_(false) { } 230 231 Range(int32_t lower, int32_t upper) 232 : lower_(lower), 233 upper_(upper), 234 next_(NULL), 235 can_be_minus_zero_(false) { } 236 237 int32_t upper() const { return upper_; } 238 int32_t lower() const { return lower_; } 239 Range* next() const { return next_; } 240 Range* CopyClearLower(Zone* zone) const { 241 return new(zone) Range(kMinInt, upper_); 242 } 243 Range* CopyClearUpper(Zone* zone) const { 244 return new(zone) Range(lower_, kMaxInt); 245 } 246 Range* Copy(Zone* zone) const { 247 Range* result = new(zone) Range(lower_, upper_); 248 result->set_can_be_minus_zero(CanBeMinusZero()); 249 return result; 250 } 251 int32_t Mask() const; 252 void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; } 253 bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; } 254 bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; } 255 bool CanBeNegative() const { return lower_ < 0; } 256 bool Includes(int value) const { return lower_ <= value && upper_ >= value; } 257 bool IsMostGeneric() const { 258 return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero(); 259 } 260 bool IsInSmiRange() const { 261 return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue; 262 } 263 void KeepOrder(); 264 #ifdef DEBUG 265 void Verify() const; 266 #endif 267 268 void StackUpon(Range* other) { 269 Intersect(other); 270 next_ = other; 271 } 272 273 void Intersect(Range* other); 274 void Union(Range* other); 275 276 void AddConstant(int32_t value); 277 void Sar(int32_t value); 278 void Shl(int32_t value); 279 bool AddAndCheckOverflow(Range* other); 280 bool SubAndCheckOverflow(Range* other); 281 bool MulAndCheckOverflow(Range* other); 282 283 private: 284 int32_t lower_; 285 int32_t upper_; 286 Range* next_; 287 bool can_be_minus_zero_; 288 }; 289 290 291 class Representation { 292 public: 293 enum Kind { 294 kNone, 295 kTagged, 296 kDouble, 297 kInteger32, 298 kExternal, 299 kNumRepresentations 300 }; 301 302 Representation() : kind_(kNone) { } 303 304 static Representation None() { return Representation(kNone); } 305 static Representation Tagged() { return Representation(kTagged); } 306 static Representation Integer32() { return Representation(kInteger32); } 307 static Representation Double() { return Representation(kDouble); } 308 static Representation External() { return Representation(kExternal); } 309 310 bool Equals(const Representation& other) { 311 return kind_ == other.kind_; 312 } 313 314 Kind kind() const { return static_cast<Kind>(kind_); } 315 bool IsNone() const { return kind_ == kNone; } 316 bool IsTagged() const { return kind_ == kTagged; } 317 bool IsInteger32() const { return kind_ == kInteger32; } 318 bool IsDouble() const { return kind_ == kDouble; } 319 bool IsExternal() const { return kind_ == kExternal; } 320 bool IsSpecialization() const { 321 return kind_ == kInteger32 || kind_ == kDouble; 322 } 323 const char* Mnemonic() const; 324 325 private: 326 explicit Representation(Kind k) : kind_(k) { } 327 328 // Make sure kind fits in int8. 329 STATIC_ASSERT(kNumRepresentations <= (1 << kBitsPerByte)); 330 331 int8_t kind_; 332 }; 333 334 335 class HType { 336 public: 337 HType() : type_(kUninitialized) { } 338 339 static HType Tagged() { return HType(kTagged); } 340 static HType TaggedPrimitive() { return HType(kTaggedPrimitive); } 341 static HType TaggedNumber() { return HType(kTaggedNumber); } 342 static HType Smi() { return HType(kSmi); } 343 static HType HeapNumber() { return HType(kHeapNumber); } 344 static HType String() { return HType(kString); } 345 static HType Boolean() { return HType(kBoolean); } 346 static HType NonPrimitive() { return HType(kNonPrimitive); } 347 static HType JSArray() { return HType(kJSArray); } 348 static HType JSObject() { return HType(kJSObject); } 349 static HType Uninitialized() { return HType(kUninitialized); } 350 351 // Return the weakest (least precise) common type. 352 HType Combine(HType other) { 353 return HType(static_cast<Type>(type_ & other.type_)); 354 } 355 356 bool Equals(const HType& other) { 357 return type_ == other.type_; 358 } 359 360 bool IsSubtypeOf(const HType& other) { 361 return Combine(other).Equals(other); 362 } 363 364 bool IsTagged() { 365 ASSERT(type_ != kUninitialized); 366 return ((type_ & kTagged) == kTagged); 367 } 368 369 bool IsTaggedPrimitive() { 370 ASSERT(type_ != kUninitialized); 371 return ((type_ & kTaggedPrimitive) == kTaggedPrimitive); 372 } 373 374 bool IsTaggedNumber() { 375 ASSERT(type_ != kUninitialized); 376 return ((type_ & kTaggedNumber) == kTaggedNumber); 377 } 378 379 bool IsSmi() { 380 ASSERT(type_ != kUninitialized); 381 return ((type_ & kSmi) == kSmi); 382 } 383 384 bool IsHeapNumber() { 385 ASSERT(type_ != kUninitialized); 386 return ((type_ & kHeapNumber) == kHeapNumber); 387 } 388 389 bool IsString() { 390 ASSERT(type_ != kUninitialized); 391 return ((type_ & kString) == kString); 392 } 393 394 bool IsBoolean() { 395 ASSERT(type_ != kUninitialized); 396 return ((type_ & kBoolean) == kBoolean); 397 } 398 399 bool IsNonPrimitive() { 400 ASSERT(type_ != kUninitialized); 401 return ((type_ & kNonPrimitive) == kNonPrimitive); 402 } 403 404 bool IsJSArray() { 405 ASSERT(type_ != kUninitialized); 406 return ((type_ & kJSArray) == kJSArray); 407 } 408 409 bool IsJSObject() { 410 ASSERT(type_ != kUninitialized); 411 return ((type_ & kJSObject) == kJSObject); 412 } 413 414 bool IsUninitialized() { 415 return type_ == kUninitialized; 416 } 417 418 bool IsHeapObject() { 419 ASSERT(type_ != kUninitialized); 420 return IsHeapNumber() || IsString() || IsNonPrimitive(); 421 } 422 423 static HType TypeFromValue(Handle<Object> value); 424 425 const char* ToString(); 426 427 private: 428 enum Type { 429 kTagged = 0x1, // 0000 0000 0000 0001 430 kTaggedPrimitive = 0x5, // 0000 0000 0000 0101 431 kTaggedNumber = 0xd, // 0000 0000 0000 1101 432 kSmi = 0x1d, // 0000 0000 0001 1101 433 kHeapNumber = 0x2d, // 0000 0000 0010 1101 434 kString = 0x45, // 0000 0000 0100 0101 435 kBoolean = 0x85, // 0000 0000 1000 0101 436 kNonPrimitive = 0x101, // 0000 0001 0000 0001 437 kJSObject = 0x301, // 0000 0011 0000 0001 438 kJSArray = 0x701, // 0000 0111 0000 0001 439 kUninitialized = 0x1fff // 0001 1111 1111 1111 440 }; 441 442 // Make sure type fits in int16. 443 STATIC_ASSERT(kUninitialized < (1 << (2 * kBitsPerByte))); 444 445 explicit HType(Type t) : type_(t) { } 446 447 int16_t type_; 448 }; 449 450 451 class HUseListNode: public ZoneObject { 452 public: 453 HUseListNode(HValue* value, int index, HUseListNode* tail) 454 : tail_(tail), value_(value), index_(index) { 455 } 456 457 HUseListNode* tail(); 458 HValue* value() const { return value_; } 459 int index() const { return index_; } 460 461 void set_tail(HUseListNode* list) { tail_ = list; } 462 463 #ifdef DEBUG 464 void Zap() { 465 tail_ = reinterpret_cast<HUseListNode*>(1); 466 value_ = NULL; 467 index_ = -1; 468 } 469 #endif 470 471 private: 472 HUseListNode* tail_; 473 HValue* value_; 474 int index_; 475 }; 476 477 478 // We reuse use list nodes behind the scenes as uses are added and deleted. 479 // This class is the safe way to iterate uses while deleting them. 480 class HUseIterator BASE_EMBEDDED { 481 public: 482 bool Done() { return current_ == NULL; } 483 void Advance(); 484 485 HValue* value() { 486 ASSERT(!Done()); 487 return value_; 488 } 489 490 int index() { 491 ASSERT(!Done()); 492 return index_; 493 } 494 495 private: 496 explicit HUseIterator(HUseListNode* head); 497 498 HUseListNode* current_; 499 HUseListNode* next_; 500 HValue* value_; 501 int index_; 502 503 friend class HValue; 504 }; 505 506 507 // There must be one corresponding kDepends flag for every kChanges flag and 508 // the order of the kChanges flags must be exactly the same as of the kDepends 509 // flags. 510 enum GVNFlag { 511 // Declare global value numbering flags. 512 #define DECLARE_FLAG(type) kChanges##type, kDependsOn##type, 513 GVN_FLAG_LIST(DECLARE_FLAG) 514 #undef DECLARE_FLAG 515 kAfterLastFlag, 516 kLastFlag = kAfterLastFlag - 1 517 }; 518 519 typedef EnumSet<GVNFlag> GVNFlagSet; 520 521 522 class HValue: public ZoneObject { 523 public: 524 static const int kNoNumber = -1; 525 526 enum Flag { 527 kFlexibleRepresentation, 528 // Participate in Global Value Numbering, i.e. elimination of 529 // unnecessary recomputations. If an instruction sets this flag, it must 530 // implement DataEquals(), which will be used to determine if other 531 // occurrences of the instruction are indeed the same. 532 kUseGVN, 533 kCanOverflow, 534 kBailoutOnMinusZero, 535 kCanBeDivByZero, 536 kDeoptimizeOnUndefined, 537 kIsArguments, 538 kTruncatingToInt32, 539 kIsDead, 540 kLastFlag = kIsDead 541 }; 542 543 STATIC_ASSERT(kLastFlag < kBitsPerInt); 544 545 static const int kChangesToDependsFlagsLeftShift = 1; 546 547 static GVNFlagSet ConvertChangesToDependsFlags(GVNFlagSet flags) { 548 return GVNFlagSet(flags.ToIntegral() << kChangesToDependsFlagsLeftShift); 549 } 550 551 static HValue* cast(HValue* value) { return value; } 552 553 enum Opcode { 554 // Declare a unique enum value for each hydrogen instruction. 555 #define DECLARE_OPCODE(type) k##type, 556 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE) 557 kPhi 558 #undef DECLARE_OPCODE 559 }; 560 virtual Opcode opcode() const = 0; 561 562 // Declare a non-virtual predicates for each concrete HInstruction or HValue. 563 #define DECLARE_PREDICATE(type) \ 564 bool Is##type() const { return opcode() == k##type; } 565 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE) 566 #undef DECLARE_PREDICATE 567 bool IsPhi() const { return opcode() == kPhi; } 568 569 // Declare virtual predicates for abstract HInstruction or HValue 570 #define DECLARE_PREDICATE(type) \ 571 virtual bool Is##type() const { return false; } 572 HYDROGEN_ABSTRACT_INSTRUCTION_LIST(DECLARE_PREDICATE) 573 #undef DECLARE_PREDICATE 574 575 HValue() : block_(NULL), 576 id_(kNoNumber), 577 type_(HType::Tagged()), 578 use_list_(NULL), 579 range_(NULL), 580 flags_(0) {} 581 virtual ~HValue() {} 582 583 HBasicBlock* block() const { return block_; } 584 void SetBlock(HBasicBlock* block); 585 int LoopWeight() const; 586 587 int id() const { return id_; } 588 void set_id(int id) { id_ = id; } 589 590 HUseIterator uses() const { return HUseIterator(use_list_); } 591 592 virtual bool EmitAtUses() { return false; } 593 Representation representation() const { return representation_; } 594 void ChangeRepresentation(Representation r) { 595 // Representation was already set and is allowed to be changed. 596 ASSERT(!r.IsNone()); 597 ASSERT(CheckFlag(kFlexibleRepresentation)); 598 RepresentationChanged(r); 599 representation_ = r; 600 } 601 void AssumeRepresentation(Representation r); 602 603 virtual bool IsConvertibleToInteger() const { return true; } 604 605 HType type() const { return type_; } 606 void set_type(HType new_type) { 607 ASSERT(new_type.IsSubtypeOf(type_)); 608 type_ = new_type; 609 } 610 611 // An operation needs to override this function iff: 612 // 1) it can produce an int32 output. 613 // 2) the true value of its output can potentially be minus zero. 614 // The implementation must set a flag so that it bails out in the case where 615 // it would otherwise output what should be a minus zero as an int32 zero. 616 // If the operation also exists in a form that takes int32 and outputs int32 617 // then the operation should return its input value so that we can propagate 618 // back. There are three operations that need to propagate back to more than 619 // one input. They are phi and binary div and mul. They always return NULL 620 // and expect the caller to take care of things. 621 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) { 622 visited->Add(id()); 623 return NULL; 624 } 625 626 bool IsDefinedAfter(HBasicBlock* other) const; 627 628 // Operands. 629 virtual int OperandCount() = 0; 630 virtual HValue* OperandAt(int index) = 0; 631 void SetOperandAt(int index, HValue* value); 632 633 void DeleteAndReplaceWith(HValue* other); 634 void ReplaceAllUsesWith(HValue* other); 635 bool HasNoUses() const { return use_list_ == NULL; } 636 bool HasMultipleUses() const { 637 return use_list_ != NULL && use_list_->tail() != NULL; 638 } 639 int UseCount() const; 640 641 // Mark this HValue as dead and to be removed from other HValues' use lists. 642 void Kill(); 643 644 int flags() const { return flags_; } 645 void SetFlag(Flag f) { flags_ |= (1 << f); } 646 void ClearFlag(Flag f) { flags_ &= ~(1 << f); } 647 bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; } 648 649 // Returns true if the flag specified is set for all uses, false otherwise. 650 bool CheckUsesForFlag(Flag f); 651 652 GVNFlagSet gvn_flags() const { return gvn_flags_; } 653 void SetGVNFlag(GVNFlag f) { gvn_flags_.Add(f); } 654 void ClearGVNFlag(GVNFlag f) { gvn_flags_.Remove(f); } 655 bool CheckGVNFlag(GVNFlag f) const { return gvn_flags_.Contains(f); } 656 void SetAllSideEffects() { gvn_flags_.Add(AllSideEffectsFlagSet()); } 657 void ClearAllSideEffects() { 658 gvn_flags_.Remove(AllSideEffectsFlagSet()); 659 } 660 bool HasSideEffects() const { 661 return gvn_flags_.ContainsAnyOf(AllSideEffectsFlagSet()); 662 } 663 bool HasObservableSideEffects() const { 664 return gvn_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet()); 665 } 666 667 GVNFlagSet DependsOnFlags() const { 668 GVNFlagSet result = gvn_flags_; 669 result.Intersect(AllDependsOnFlagSet()); 670 return result; 671 } 672 673 GVNFlagSet SideEffectFlags() const { 674 GVNFlagSet result = gvn_flags_; 675 result.Intersect(AllSideEffectsFlagSet()); 676 return result; 677 } 678 679 GVNFlagSet ChangesFlags() const { 680 GVNFlagSet result = gvn_flags_; 681 result.Intersect(AllChangesFlagSet()); 682 return result; 683 } 684 685 GVNFlagSet ObservableChangesFlags() const { 686 GVNFlagSet result = gvn_flags_; 687 result.Intersect(AllChangesFlagSet()); 688 result.Intersect(AllObservableSideEffectsFlagSet()); 689 return result; 690 } 691 692 Range* range() const { return range_; } 693 bool HasRange() const { return range_ != NULL; } 694 void AddNewRange(Range* r, Zone* zone); 695 void RemoveLastAddedRange(); 696 void ComputeInitialRange(Zone* zone); 697 698 // Representation helpers. 699 virtual Representation RequiredInputRepresentation(int index) = 0; 700 701 virtual Representation InferredRepresentation() { 702 return representation(); 703 } 704 705 // This gives the instruction an opportunity to replace itself with an 706 // instruction that does the same in some better way. To replace an 707 // instruction with a new one, first add the new instruction to the graph, 708 // then return it. Return NULL to have the instruction deleted. 709 virtual HValue* Canonicalize() { return this; } 710 711 bool Equals(HValue* other); 712 virtual intptr_t Hashcode(); 713 714 // Printing support. 715 virtual void PrintTo(StringStream* stream) = 0; 716 void PrintNameTo(StringStream* stream); 717 void PrintTypeTo(StringStream* stream); 718 void PrintRangeTo(StringStream* stream); 719 void PrintChangesTo(StringStream* stream); 720 721 const char* Mnemonic() const; 722 723 // Updated the inferred type of this instruction and returns true if 724 // it has changed. 725 bool UpdateInferredType(); 726 727 virtual HType CalculateInferredType(); 728 729 #ifdef DEBUG 730 virtual void Verify() = 0; 731 #endif 732 733 protected: 734 // This function must be overridden for instructions with flag kUseGVN, to 735 // compare the non-Operand parts of the instruction. 736 virtual bool DataEquals(HValue* other) { 737 UNREACHABLE(); 738 return false; 739 } 740 virtual void RepresentationChanged(Representation to) { } 741 virtual Range* InferRange(Zone* zone); 742 virtual void DeleteFromGraph() = 0; 743 virtual void InternalSetOperandAt(int index, HValue* value) = 0; 744 void clear_block() { 745 ASSERT(block_ != NULL); 746 block_ = NULL; 747 } 748 749 void set_representation(Representation r) { 750 // Representation is set-once. 751 ASSERT(representation_.IsNone() && !r.IsNone()); 752 representation_ = r; 753 } 754 755 static GVNFlagSet AllDependsOnFlagSet() { 756 GVNFlagSet result; 757 // Create changes mask. 758 #define ADD_FLAG(type) result.Add(kDependsOn##type); 759 GVN_FLAG_LIST(ADD_FLAG) 760 #undef ADD_FLAG 761 return result; 762 } 763 764 static GVNFlagSet AllChangesFlagSet() { 765 GVNFlagSet result; 766 // Create changes mask. 767 #define ADD_FLAG(type) result.Add(kChanges##type); 768 GVN_FLAG_LIST(ADD_FLAG) 769 #undef ADD_FLAG 770 return result; 771 } 772 773 // A flag mask to mark an instruction as having arbitrary side effects. 774 static GVNFlagSet AllSideEffectsFlagSet() { 775 GVNFlagSet result = AllChangesFlagSet(); 776 result.Remove(kChangesOsrEntries); 777 return result; 778 } 779 780 // A flag mask of all side effects that can make observable changes in 781 // an executing program (i.e. are not safe to repeat, move or remove); 782 static GVNFlagSet AllObservableSideEffectsFlagSet() { 783 GVNFlagSet result = AllChangesFlagSet(); 784 result.Remove(kChangesElementsKind); 785 result.Remove(kChangesElementsPointer); 786 result.Remove(kChangesMaps); 787 return result; 788 } 789 790 // Remove the matching use from the use list if present. Returns the 791 // removed list node or NULL. 792 HUseListNode* RemoveUse(HValue* value, int index); 793 794 void RegisterUse(int index, HValue* new_value); 795 796 HBasicBlock* block_; 797 798 // The id of this instruction in the hydrogen graph, assigned when first 799 // added to the graph. Reflects creation order. 800 int id_; 801 802 Representation representation_; 803 HType type_; 804 HUseListNode* use_list_; 805 Range* range_; 806 int flags_; 807 GVNFlagSet gvn_flags_; 808 809 private: 810 DISALLOW_COPY_AND_ASSIGN(HValue); 811 }; 812 813 814 class HInstruction: public HValue { 815 public: 816 HInstruction* next() const { return next_; } 817 HInstruction* previous() const { return previous_; } 818 819 virtual void PrintTo(StringStream* stream); 820 virtual void PrintDataTo(StringStream* stream) { } 821 822 bool IsLinked() const { return block() != NULL; } 823 void Unlink(); 824 void InsertBefore(HInstruction* next); 825 void InsertAfter(HInstruction* previous); 826 827 int position() const { return position_; } 828 bool has_position() const { return position_ != RelocInfo::kNoPosition; } 829 void set_position(int position) { position_ = position; } 830 831 bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); } 832 833 virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0; 834 835 #ifdef DEBUG 836 virtual void Verify(); 837 #endif 838 839 virtual bool IsCall() { return false; } 840 841 DECLARE_ABSTRACT_INSTRUCTION(Instruction) 842 843 protected: 844 HInstruction() 845 : next_(NULL), 846 previous_(NULL), 847 position_(RelocInfo::kNoPosition) { 848 SetGVNFlag(kDependsOnOsrEntries); 849 } 850 851 virtual void DeleteFromGraph() { Unlink(); } 852 853 private: 854 void InitializeAsFirst(HBasicBlock* block) { 855 ASSERT(!IsLinked()); 856 SetBlock(block); 857 } 858 859 void PrintMnemonicTo(StringStream* stream); 860 861 HInstruction* next_; 862 HInstruction* previous_; 863 int position_; 864 865 friend class HBasicBlock; 866 }; 867 868 869 template<int V> 870 class HTemplateInstruction : public HInstruction { 871 public: 872 int OperandCount() { return V; } 873 HValue* OperandAt(int i) { return inputs_[i]; } 874 875 protected: 876 void InternalSetOperandAt(int i, HValue* value) { inputs_[i] = value; } 877 878 private: 879 EmbeddedContainer<HValue*, V> inputs_; 880 }; 881 882 883 class HControlInstruction: public HInstruction { 884 public: 885 virtual HBasicBlock* SuccessorAt(int i) = 0; 886 virtual int SuccessorCount() = 0; 887 virtual void SetSuccessorAt(int i, HBasicBlock* block) = 0; 888 889 virtual void PrintDataTo(StringStream* stream); 890 891 HBasicBlock* FirstSuccessor() { 892 return SuccessorCount() > 0 ? SuccessorAt(0) : NULL; 893 } 894 HBasicBlock* SecondSuccessor() { 895 return SuccessorCount() > 1 ? SuccessorAt(1) : NULL; 896 } 897 898 DECLARE_ABSTRACT_INSTRUCTION(ControlInstruction) 899 }; 900 901 902 class HSuccessorIterator BASE_EMBEDDED { 903 public: 904 explicit HSuccessorIterator(HControlInstruction* instr) 905 : instr_(instr), current_(0) { } 906 907 bool Done() { return current_ >= instr_->SuccessorCount(); } 908 HBasicBlock* Current() { return instr_->SuccessorAt(current_); } 909 void Advance() { current_++; } 910 911 private: 912 HControlInstruction* instr_; 913 int current_; 914 }; 915 916 917 template<int S, int V> 918 class HTemplateControlInstruction: public HControlInstruction { 919 public: 920 int SuccessorCount() { return S; } 921 HBasicBlock* SuccessorAt(int i) { return successors_[i]; } 922 void SetSuccessorAt(int i, HBasicBlock* block) { successors_[i] = block; } 923 924 int OperandCount() { return V; } 925 HValue* OperandAt(int i) { return inputs_[i]; } 926 927 928 protected: 929 void InternalSetOperandAt(int i, HValue* value) { inputs_[i] = value; } 930 931 private: 932 EmbeddedContainer<HBasicBlock*, S> successors_; 933 EmbeddedContainer<HValue*, V> inputs_; 934 }; 935 936 937 class HBlockEntry: public HTemplateInstruction<0> { 938 public: 939 virtual Representation RequiredInputRepresentation(int index) { 940 return Representation::None(); 941 } 942 943 DECLARE_CONCRETE_INSTRUCTION(BlockEntry) 944 }; 945 946 947 // We insert soft-deoptimize when we hit code with unknown typefeedback, 948 // so that we get a chance of re-optimizing with useful typefeedback. 949 // HSoftDeoptimize does not end a basic block as opposed to HDeoptimize. 950 class HSoftDeoptimize: public HTemplateInstruction<0> { 951 public: 952 virtual Representation RequiredInputRepresentation(int index) { 953 return Representation::None(); 954 } 955 956 DECLARE_CONCRETE_INSTRUCTION(SoftDeoptimize) 957 }; 958 959 960 class HDeoptimize: public HControlInstruction { 961 public: 962 explicit HDeoptimize(int environment_length) : values_(environment_length) { } 963 964 virtual Representation RequiredInputRepresentation(int index) { 965 return Representation::None(); 966 } 967 968 virtual int OperandCount() { return values_.length(); } 969 virtual HValue* OperandAt(int index) { return values_[index]; } 970 virtual void PrintDataTo(StringStream* stream); 971 972 virtual int SuccessorCount() { return 0; } 973 virtual HBasicBlock* SuccessorAt(int i) { 974 UNREACHABLE(); 975 return NULL; 976 } 977 virtual void SetSuccessorAt(int i, HBasicBlock* block) { 978 UNREACHABLE(); 979 } 980 981 void AddEnvironmentValue(HValue* value) { 982 values_.Add(NULL); 983 SetOperandAt(values_.length() - 1, value); 984 } 985 986 DECLARE_CONCRETE_INSTRUCTION(Deoptimize) 987 988 enum UseEnvironment { 989 kNoUses, 990 kUseAll 991 }; 992 993 protected: 994 virtual void InternalSetOperandAt(int index, HValue* value) { 995 values_[index] = value; 996 } 997 998 private: 999 ZoneList<HValue*> values_; 1000 }; 1001 1002 1003 class HGoto: public HTemplateControlInstruction<1, 0> { 1004 public: 1005 explicit HGoto(HBasicBlock* target) { 1006 SetSuccessorAt(0, target); 1007 } 1008 1009 virtual Representation RequiredInputRepresentation(int index) { 1010 return Representation::None(); 1011 } 1012 1013 virtual void PrintDataTo(StringStream* stream); 1014 1015 DECLARE_CONCRETE_INSTRUCTION(Goto) 1016 }; 1017 1018 1019 class HUnaryControlInstruction: public HTemplateControlInstruction<2, 1> { 1020 public: 1021 HUnaryControlInstruction(HValue* value, 1022 HBasicBlock* true_target, 1023 HBasicBlock* false_target) { 1024 SetOperandAt(0, value); 1025 SetSuccessorAt(0, true_target); 1026 SetSuccessorAt(1, false_target); 1027 } 1028 1029 virtual void PrintDataTo(StringStream* stream); 1030 1031 HValue* value() { return OperandAt(0); } 1032 }; 1033 1034 1035 class HBranch: public HUnaryControlInstruction { 1036 public: 1037 HBranch(HValue* value, 1038 HBasicBlock* true_target, 1039 HBasicBlock* false_target, 1040 ToBooleanStub::Types expected_input_types = ToBooleanStub::no_types()) 1041 : HUnaryControlInstruction(value, true_target, false_target), 1042 expected_input_types_(expected_input_types) { 1043 ASSERT(true_target != NULL && false_target != NULL); 1044 } 1045 explicit HBranch(HValue* value) 1046 : HUnaryControlInstruction(value, NULL, NULL) { } 1047 1048 1049 virtual Representation RequiredInputRepresentation(int index) { 1050 return Representation::None(); 1051 } 1052 1053 ToBooleanStub::Types expected_input_types() const { 1054 return expected_input_types_; 1055 } 1056 1057 DECLARE_CONCRETE_INSTRUCTION(Branch) 1058 1059 private: 1060 ToBooleanStub::Types expected_input_types_; 1061 }; 1062 1063 1064 class HCompareMap: public HUnaryControlInstruction { 1065 public: 1066 HCompareMap(HValue* value, 1067 Handle<Map> map, 1068 HBasicBlock* true_target, 1069 HBasicBlock* false_target) 1070 : HUnaryControlInstruction(value, true_target, false_target), 1071 map_(map) { 1072 ASSERT(true_target != NULL); 1073 ASSERT(false_target != NULL); 1074 ASSERT(!map.is_null()); 1075 } 1076 1077 virtual void PrintDataTo(StringStream* stream); 1078 1079 Handle<Map> map() const { return map_; } 1080 1081 virtual Representation RequiredInputRepresentation(int index) { 1082 return Representation::Tagged(); 1083 } 1084 1085 DECLARE_CONCRETE_INSTRUCTION(CompareMap) 1086 1087 private: 1088 Handle<Map> map_; 1089 }; 1090 1091 1092 class HReturn: public HTemplateControlInstruction<0, 1> { 1093 public: 1094 explicit HReturn(HValue* value) { 1095 SetOperandAt(0, value); 1096 } 1097 1098 virtual Representation RequiredInputRepresentation(int index) { 1099 return Representation::Tagged(); 1100 } 1101 1102 virtual void PrintDataTo(StringStream* stream); 1103 1104 HValue* value() { return OperandAt(0); } 1105 1106 DECLARE_CONCRETE_INSTRUCTION(Return) 1107 }; 1108 1109 1110 class HAbnormalExit: public HTemplateControlInstruction<0, 0> { 1111 public: 1112 virtual Representation RequiredInputRepresentation(int index) { 1113 return Representation::None(); 1114 } 1115 1116 DECLARE_CONCRETE_INSTRUCTION(AbnormalExit) 1117 }; 1118 1119 1120 class HUnaryOperation: public HTemplateInstruction<1> { 1121 public: 1122 explicit HUnaryOperation(HValue* value) { 1123 SetOperandAt(0, value); 1124 } 1125 1126 static HUnaryOperation* cast(HValue* value) { 1127 return reinterpret_cast<HUnaryOperation*>(value); 1128 } 1129 1130 HValue* value() { return OperandAt(0); } 1131 virtual void PrintDataTo(StringStream* stream); 1132 }; 1133 1134 1135 class HThrow: public HTemplateInstruction<2> { 1136 public: 1137 HThrow(HValue* context, HValue* value) { 1138 SetOperandAt(0, context); 1139 SetOperandAt(1, value); 1140 SetAllSideEffects(); 1141 } 1142 1143 virtual Representation RequiredInputRepresentation(int index) { 1144 return Representation::Tagged(); 1145 } 1146 1147 HValue* context() { return OperandAt(0); } 1148 HValue* value() { return OperandAt(1); } 1149 1150 DECLARE_CONCRETE_INSTRUCTION(Throw) 1151 }; 1152 1153 1154 class HUseConst: public HUnaryOperation { 1155 public: 1156 explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { } 1157 1158 virtual Representation RequiredInputRepresentation(int index) { 1159 return Representation::None(); 1160 } 1161 1162 DECLARE_CONCRETE_INSTRUCTION(UseConst) 1163 }; 1164 1165 1166 class HForceRepresentation: public HTemplateInstruction<1> { 1167 public: 1168 HForceRepresentation(HValue* value, Representation required_representation) { 1169 SetOperandAt(0, value); 1170 set_representation(required_representation); 1171 } 1172 1173 HValue* value() { return OperandAt(0); } 1174 1175 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); 1176 1177 virtual Representation RequiredInputRepresentation(int index) { 1178 return representation(); // Same as the output representation. 1179 } 1180 1181 DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation) 1182 }; 1183 1184 1185 class HChange: public HUnaryOperation { 1186 public: 1187 HChange(HValue* value, 1188 Representation to, 1189 bool is_truncating, 1190 bool deoptimize_on_undefined) 1191 : HUnaryOperation(value) { 1192 ASSERT(!value->representation().IsNone() && !to.IsNone()); 1193 ASSERT(!value->representation().Equals(to)); 1194 set_representation(to); 1195 set_type(HType::TaggedNumber()); 1196 SetFlag(kUseGVN); 1197 if (deoptimize_on_undefined) SetFlag(kDeoptimizeOnUndefined); 1198 if (is_truncating) SetFlag(kTruncatingToInt32); 1199 } 1200 1201 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); 1202 virtual HType CalculateInferredType(); 1203 virtual HValue* Canonicalize(); 1204 1205 Representation from() { return value()->representation(); } 1206 Representation to() { return representation(); } 1207 bool deoptimize_on_undefined() const { 1208 return CheckFlag(kDeoptimizeOnUndefined); 1209 } 1210 bool deoptimize_on_minus_zero() const { 1211 return CheckFlag(kBailoutOnMinusZero); 1212 } 1213 virtual Representation RequiredInputRepresentation(int index) { 1214 return from(); 1215 } 1216 1217 virtual Range* InferRange(Zone* zone); 1218 1219 virtual void PrintDataTo(StringStream* stream); 1220 1221 DECLARE_CONCRETE_INSTRUCTION(Change) 1222 1223 protected: 1224 virtual bool DataEquals(HValue* other) { return true; } 1225 }; 1226 1227 1228 class HClampToUint8: public HUnaryOperation { 1229 public: 1230 explicit HClampToUint8(HValue* value) 1231 : HUnaryOperation(value) { 1232 set_representation(Representation::Integer32()); 1233 SetFlag(kUseGVN); 1234 } 1235 1236 virtual Representation RequiredInputRepresentation(int index) { 1237 return Representation::None(); 1238 } 1239 1240 DECLARE_CONCRETE_INSTRUCTION(ClampToUint8) 1241 1242 protected: 1243 virtual bool DataEquals(HValue* other) { return true; } 1244 }; 1245 1246 1247 class HSimulate: public HInstruction { 1248 public: 1249 HSimulate(int ast_id, int pop_count) 1250 : ast_id_(ast_id), 1251 pop_count_(pop_count), 1252 values_(2), 1253 assigned_indexes_(2) {} 1254 virtual ~HSimulate() {} 1255 1256 virtual void PrintDataTo(StringStream* stream); 1257 1258 bool HasAstId() const { return ast_id_ != AstNode::kNoNumber; } 1259 int ast_id() const { return ast_id_; } 1260 void set_ast_id(int id) { 1261 ASSERT(!HasAstId()); 1262 ast_id_ = id; 1263 } 1264 1265 int pop_count() const { return pop_count_; } 1266 const ZoneList<HValue*>* values() const { return &values_; } 1267 int GetAssignedIndexAt(int index) const { 1268 ASSERT(HasAssignedIndexAt(index)); 1269 return assigned_indexes_[index]; 1270 } 1271 bool HasAssignedIndexAt(int index) const { 1272 return assigned_indexes_[index] != kNoIndex; 1273 } 1274 void AddAssignedValue(int index, HValue* value) { 1275 AddValue(index, value); 1276 } 1277 void AddPushedValue(HValue* value) { 1278 AddValue(kNoIndex, value); 1279 } 1280 virtual int OperandCount() { return values_.length(); } 1281 virtual HValue* OperandAt(int index) { return values_[index]; } 1282 1283 virtual Representation RequiredInputRepresentation(int index) { 1284 return Representation::None(); 1285 } 1286 1287 DECLARE_CONCRETE_INSTRUCTION(Simulate) 1288 1289 #ifdef DEBUG 1290 virtual void Verify(); 1291 #endif 1292 1293 protected: 1294 virtual void InternalSetOperandAt(int index, HValue* value) { 1295 values_[index] = value; 1296 } 1297 1298 private: 1299 static const int kNoIndex = -1; 1300 void AddValue(int index, HValue* value) { 1301 assigned_indexes_.Add(index); 1302 // Resize the list of pushed values. 1303 values_.Add(NULL); 1304 // Set the operand through the base method in HValue to make sure that the 1305 // use lists are correctly updated. 1306 SetOperandAt(values_.length() - 1, value); 1307 } 1308 int ast_id_; 1309 int pop_count_; 1310 ZoneList<HValue*> values_; 1311 ZoneList<int> assigned_indexes_; 1312 }; 1313 1314 1315 class HStackCheck: public HTemplateInstruction<1> { 1316 public: 1317 enum Type { 1318 kFunctionEntry, 1319 kBackwardsBranch 1320 }; 1321 1322 HStackCheck(HValue* context, Type type) : type_(type) { 1323 SetOperandAt(0, context); 1324 } 1325 1326 HValue* context() { return OperandAt(0); } 1327 1328 virtual Representation RequiredInputRepresentation(int index) { 1329 return Representation::Tagged(); 1330 } 1331 1332 void Eliminate() { 1333 // The stack check eliminator might try to eliminate the same stack 1334 // check instruction multiple times. 1335 if (IsLinked()) { 1336 DeleteFromGraph(); 1337 } 1338 } 1339 1340 bool is_function_entry() { return type_ == kFunctionEntry; } 1341 bool is_backwards_branch() { return type_ == kBackwardsBranch; } 1342 1343 DECLARE_CONCRETE_INSTRUCTION(StackCheck) 1344 1345 private: 1346 Type type_; 1347 }; 1348 1349 1350 class HEnterInlined: public HTemplateInstruction<0> { 1351 public: 1352 HEnterInlined(Handle<JSFunction> closure, 1353 int arguments_count, 1354 FunctionLiteral* function, 1355 CallKind call_kind, 1356 bool is_construct, 1357 Variable* arguments) 1358 : closure_(closure), 1359 arguments_count_(arguments_count), 1360 function_(function), 1361 call_kind_(call_kind), 1362 is_construct_(is_construct), 1363 arguments_(arguments) { 1364 } 1365 1366 virtual void PrintDataTo(StringStream* stream); 1367 1368 Handle<JSFunction> closure() const { return closure_; } 1369 int arguments_count() const { return arguments_count_; } 1370 FunctionLiteral* function() const { return function_; } 1371 CallKind call_kind() const { return call_kind_; } 1372 bool is_construct() const { return is_construct_; } 1373 1374 virtual Representation RequiredInputRepresentation(int index) { 1375 return Representation::None(); 1376 } 1377 1378 Variable* arguments() { return arguments_; } 1379 1380 DECLARE_CONCRETE_INSTRUCTION(EnterInlined) 1381 1382 private: 1383 Handle<JSFunction> closure_; 1384 int arguments_count_; 1385 FunctionLiteral* function_; 1386 CallKind call_kind_; 1387 bool is_construct_; 1388 Variable* arguments_; 1389 }; 1390 1391 1392 class HLeaveInlined: public HTemplateInstruction<0> { 1393 public: 1394 HLeaveInlined() {} 1395 1396 virtual Representation RequiredInputRepresentation(int index) { 1397 return Representation::None(); 1398 } 1399 1400 DECLARE_CONCRETE_INSTRUCTION(LeaveInlined) 1401 }; 1402 1403 1404 class HPushArgument: public HUnaryOperation { 1405 public: 1406 explicit HPushArgument(HValue* value) : HUnaryOperation(value) { 1407 set_representation(Representation::Tagged()); 1408 } 1409 1410 virtual Representation RequiredInputRepresentation(int index) { 1411 return Representation::Tagged(); 1412 } 1413 1414 HValue* argument() { return OperandAt(0); } 1415 1416 DECLARE_CONCRETE_INSTRUCTION(PushArgument) 1417 }; 1418 1419 1420 class HThisFunction: public HTemplateInstruction<0> { 1421 public: 1422 explicit HThisFunction(Handle<JSFunction> closure) : closure_(closure) { 1423 set_representation(Representation::Tagged()); 1424 SetFlag(kUseGVN); 1425 } 1426 1427 virtual Representation RequiredInputRepresentation(int index) { 1428 return Representation::None(); 1429 } 1430 1431 Handle<JSFunction> closure() const { return closure_; } 1432 1433 DECLARE_CONCRETE_INSTRUCTION(ThisFunction) 1434 1435 protected: 1436 virtual bool DataEquals(HValue* other) { 1437 HThisFunction* b = HThisFunction::cast(other); 1438 return *closure() == *b->closure(); 1439 } 1440 1441 private: 1442 Handle<JSFunction> closure_; 1443 }; 1444 1445 1446 class HContext: public HTemplateInstruction<0> { 1447 public: 1448 HContext() { 1449 set_representation(Representation::Tagged()); 1450 SetFlag(kUseGVN); 1451 } 1452 1453 virtual Representation RequiredInputRepresentation(int index) { 1454 return Representation::None(); 1455 } 1456 1457 DECLARE_CONCRETE_INSTRUCTION(Context) 1458 1459 protected: 1460 virtual bool DataEquals(HValue* other) { return true; } 1461 }; 1462 1463 1464 class HOuterContext: public HUnaryOperation { 1465 public: 1466 explicit HOuterContext(HValue* inner) : HUnaryOperation(inner) { 1467 set_representation(Representation::Tagged()); 1468 SetFlag(kUseGVN); 1469 } 1470 1471 DECLARE_CONCRETE_INSTRUCTION(OuterContext); 1472 1473 virtual Representation RequiredInputRepresentation(int index) { 1474 return Representation::Tagged(); 1475 } 1476 1477 protected: 1478 virtual bool DataEquals(HValue* other) { return true; } 1479 }; 1480 1481 1482 class HDeclareGlobals: public HUnaryOperation { 1483 public: 1484 HDeclareGlobals(HValue* context, 1485 Handle<FixedArray> pairs, 1486 int flags) 1487 : HUnaryOperation(context), 1488 pairs_(pairs), 1489 flags_(flags) { 1490 set_representation(Representation::Tagged()); 1491 SetAllSideEffects(); 1492 } 1493 1494 HValue* context() { return OperandAt(0); } 1495 Handle<FixedArray> pairs() const { return pairs_; } 1496 int flags() const { return flags_; } 1497 1498 DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals) 1499 1500 virtual Representation RequiredInputRepresentation(int index) { 1501 return Representation::Tagged(); 1502 } 1503 private: 1504 Handle<FixedArray> pairs_; 1505 int flags_; 1506 }; 1507 1508 1509 class HGlobalObject: public HUnaryOperation { 1510 public: 1511 explicit HGlobalObject(HValue* context) : HUnaryOperation(context) { 1512 set_representation(Representation::Tagged()); 1513 SetFlag(kUseGVN); 1514 } 1515 1516 DECLARE_CONCRETE_INSTRUCTION(GlobalObject) 1517 1518 virtual Representation RequiredInputRepresentation(int index) { 1519 return Representation::Tagged(); 1520 } 1521 1522 protected: 1523 virtual bool DataEquals(HValue* other) { return true; } 1524 }; 1525 1526 1527 class HGlobalReceiver: public HUnaryOperation { 1528 public: 1529 explicit HGlobalReceiver(HValue* global_object) 1530 : HUnaryOperation(global_object) { 1531 set_representation(Representation::Tagged()); 1532 SetFlag(kUseGVN); 1533 } 1534 1535 DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver) 1536 1537 virtual Representation RequiredInputRepresentation(int index) { 1538 return Representation::Tagged(); 1539 } 1540 1541 protected: 1542 virtual bool DataEquals(HValue* other) { return true; } 1543 }; 1544 1545 1546 template <int V> 1547 class HCall: public HTemplateInstruction<V> { 1548 public: 1549 // The argument count includes the receiver. 1550 explicit HCall<V>(int argument_count) : argument_count_(argument_count) { 1551 this->set_representation(Representation::Tagged()); 1552 this->SetAllSideEffects(); 1553 } 1554 1555 virtual HType CalculateInferredType() { return HType::Tagged(); } 1556 1557 virtual int argument_count() const { return argument_count_; } 1558 1559 virtual bool IsCall() { return true; } 1560 1561 private: 1562 int argument_count_; 1563 }; 1564 1565 1566 class HUnaryCall: public HCall<1> { 1567 public: 1568 HUnaryCall(HValue* value, int argument_count) 1569 : HCall<1>(argument_count) { 1570 SetOperandAt(0, value); 1571 } 1572 1573 virtual Representation RequiredInputRepresentation(int index) { 1574 return Representation::Tagged(); 1575 } 1576 1577 virtual void PrintDataTo(StringStream* stream); 1578 1579 HValue* value() { return OperandAt(0); } 1580 }; 1581 1582 1583 class HBinaryCall: public HCall<2> { 1584 public: 1585 HBinaryCall(HValue* first, HValue* second, int argument_count) 1586 : HCall<2>(argument_count) { 1587 SetOperandAt(0, first); 1588 SetOperandAt(1, second); 1589 } 1590 1591 virtual void PrintDataTo(StringStream* stream); 1592 1593 virtual Representation RequiredInputRepresentation(int index) { 1594 return Representation::Tagged(); 1595 } 1596 1597 HValue* first() { return OperandAt(0); } 1598 HValue* second() { return OperandAt(1); } 1599 }; 1600 1601 1602 class HInvokeFunction: public HBinaryCall { 1603 public: 1604 HInvokeFunction(HValue* context, HValue* function, int argument_count) 1605 : HBinaryCall(context, function, argument_count) { 1606 } 1607 1608 virtual Representation RequiredInputRepresentation(int index) { 1609 return Representation::Tagged(); 1610 } 1611 1612 HValue* context() { return first(); } 1613 HValue* function() { return second(); } 1614 1615 DECLARE_CONCRETE_INSTRUCTION(InvokeFunction) 1616 }; 1617 1618 1619 class HCallConstantFunction: public HCall<0> { 1620 public: 1621 HCallConstantFunction(Handle<JSFunction> function, int argument_count) 1622 : HCall<0>(argument_count), function_(function) { } 1623 1624 Handle<JSFunction> function() const { return function_; } 1625 1626 bool IsApplyFunction() const { 1627 return function_->code() == 1628 Isolate::Current()->builtins()->builtin(Builtins::kFunctionApply); 1629 } 1630 1631 virtual void PrintDataTo(StringStream* stream); 1632 1633 virtual Representation RequiredInputRepresentation(int index) { 1634 return Representation::None(); 1635 } 1636 1637 DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction) 1638 1639 private: 1640 Handle<JSFunction> function_; 1641 }; 1642 1643 1644 class HCallKeyed: public HBinaryCall { 1645 public: 1646 HCallKeyed(HValue* context, HValue* key, int argument_count) 1647 : HBinaryCall(context, key, argument_count) { 1648 } 1649 1650 virtual Representation RequiredInputRepresentation(int index) { 1651 return Representation::Tagged(); 1652 } 1653 1654 HValue* context() { return first(); } 1655 HValue* key() { return second(); } 1656 1657 DECLARE_CONCRETE_INSTRUCTION(CallKeyed) 1658 }; 1659 1660 1661 class HCallNamed: public HUnaryCall { 1662 public: 1663 HCallNamed(HValue* context, Handle<String> name, int argument_count) 1664 : HUnaryCall(context, argument_count), name_(name) { 1665 } 1666 1667 virtual void PrintDataTo(StringStream* stream); 1668 1669 HValue* context() { return value(); } 1670 Handle<String> name() const { return name_; } 1671 1672 DECLARE_CONCRETE_INSTRUCTION(CallNamed) 1673 1674 virtual Representation RequiredInputRepresentation(int index) { 1675 return Representation::Tagged(); 1676 } 1677 1678 private: 1679 Handle<String> name_; 1680 }; 1681 1682 1683 class HCallFunction: public HBinaryCall { 1684 public: 1685 HCallFunction(HValue* context, HValue* function, int argument_count) 1686 : HBinaryCall(context, function, argument_count) { 1687 } 1688 1689 HValue* context() { return first(); } 1690 HValue* function() { return second(); } 1691 1692 virtual Representation RequiredInputRepresentation(int index) { 1693 return Representation::Tagged(); 1694 } 1695 1696 DECLARE_CONCRETE_INSTRUCTION(CallFunction) 1697 }; 1698 1699 1700 class HCallGlobal: public HUnaryCall { 1701 public: 1702 HCallGlobal(HValue* context, Handle<String> name, int argument_count) 1703 : HUnaryCall(context, argument_count), name_(name) { 1704 } 1705 1706 virtual void PrintDataTo(StringStream* stream); 1707 1708 HValue* context() { return value(); } 1709 Handle<String> name() const { return name_; } 1710 1711 virtual Representation RequiredInputRepresentation(int index) { 1712 return Representation::Tagged(); 1713 } 1714 1715 DECLARE_CONCRETE_INSTRUCTION(CallGlobal) 1716 1717 private: 1718 Handle<String> name_; 1719 }; 1720 1721 1722 class HCallKnownGlobal: public HCall<0> { 1723 public: 1724 HCallKnownGlobal(Handle<JSFunction> target, int argument_count) 1725 : HCall<0>(argument_count), target_(target) { } 1726 1727 virtual void PrintDataTo(StringStream* stream); 1728 1729 Handle<JSFunction> target() const { return target_; } 1730 1731 virtual Representation RequiredInputRepresentation(int index) { 1732 return Representation::None(); 1733 } 1734 1735 DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal) 1736 1737 private: 1738 Handle<JSFunction> target_; 1739 }; 1740 1741 1742 class HCallNew: public HBinaryCall { 1743 public: 1744 HCallNew(HValue* context, HValue* constructor, int argument_count) 1745 : HBinaryCall(context, constructor, argument_count) { 1746 } 1747 1748 virtual Representation RequiredInputRepresentation(int index) { 1749 return Representation::Tagged(); 1750 } 1751 1752 HValue* context() { return first(); } 1753 HValue* constructor() { return second(); } 1754 1755 DECLARE_CONCRETE_INSTRUCTION(CallNew) 1756 }; 1757 1758 1759 class HCallRuntime: public HCall<1> { 1760 public: 1761 HCallRuntime(HValue* context, 1762 Handle<String> name, 1763 const Runtime::Function* c_function, 1764 int argument_count) 1765 : HCall<1>(argument_count), c_function_(c_function), name_(name) { 1766 SetOperandAt(0, context); 1767 } 1768 1769 virtual void PrintDataTo(StringStream* stream); 1770 1771 HValue* context() { return OperandAt(0); } 1772 const Runtime::Function* function() const { return c_function_; } 1773 Handle<String> name() const { return name_; } 1774 1775 virtual Representation RequiredInputRepresentation(int index) { 1776 return Representation::Tagged(); 1777 } 1778 1779 DECLARE_CONCRETE_INSTRUCTION(CallRuntime) 1780 1781 private: 1782 const Runtime::Function* c_function_; 1783 Handle<String> name_; 1784 }; 1785 1786 1787 class HJSArrayLength: public HTemplateInstruction<2> { 1788 public: 1789 HJSArrayLength(HValue* value, HValue* typecheck) { 1790 // The length of an array is stored as a tagged value in the array 1791 // object. It is guaranteed to be 32 bit integer, but it can be 1792 // represented as either a smi or heap number. 1793 SetOperandAt(0, value); 1794 SetOperandAt(1, typecheck); 1795 set_representation(Representation::Tagged()); 1796 SetFlag(kUseGVN); 1797 SetGVNFlag(kDependsOnArrayLengths); 1798 SetGVNFlag(kDependsOnMaps); 1799 } 1800 1801 virtual Representation RequiredInputRepresentation(int index) { 1802 return Representation::Tagged(); 1803 } 1804 1805 virtual void PrintDataTo(StringStream* stream); 1806 1807 HValue* value() { return OperandAt(0); } 1808 HValue* typecheck() { return OperandAt(1); } 1809 1810 DECLARE_CONCRETE_INSTRUCTION(JSArrayLength) 1811 1812 protected: 1813 virtual bool DataEquals(HValue* other) { return true; } 1814 }; 1815 1816 1817 class HFixedArrayBaseLength: public HUnaryOperation { 1818 public: 1819 explicit HFixedArrayBaseLength(HValue* value) : HUnaryOperation(value) { 1820 set_representation(Representation::Tagged()); 1821 SetFlag(kUseGVN); 1822 SetGVNFlag(kDependsOnArrayLengths); 1823 } 1824 1825 virtual Representation RequiredInputRepresentation(int index) { 1826 return Representation::Tagged(); 1827 } 1828 1829 DECLARE_CONCRETE_INSTRUCTION(FixedArrayBaseLength) 1830 1831 protected: 1832 virtual bool DataEquals(HValue* other) { return true; } 1833 }; 1834 1835 1836 class HElementsKind: public HUnaryOperation { 1837 public: 1838 explicit HElementsKind(HValue* value) : HUnaryOperation(value) { 1839 set_representation(Representation::Integer32()); 1840 SetFlag(kUseGVN); 1841 SetGVNFlag(kDependsOnElementsKind); 1842 } 1843 1844 virtual Representation RequiredInputRepresentation(int index) { 1845 return Representation::Tagged(); 1846 } 1847 1848 DECLARE_CONCRETE_INSTRUCTION(ElementsKind) 1849 1850 protected: 1851 virtual bool DataEquals(HValue* other) { return true; } 1852 }; 1853 1854 1855 class HBitNot: public HUnaryOperation { 1856 public: 1857 explicit HBitNot(HValue* value) : HUnaryOperation(value) { 1858 set_representation(Representation::Integer32()); 1859 SetFlag(kUseGVN); 1860 SetFlag(kTruncatingToInt32); 1861 } 1862 1863 virtual Representation RequiredInputRepresentation(int index) { 1864 return Representation::Integer32(); 1865 } 1866 virtual HType CalculateInferredType(); 1867 1868 DECLARE_CONCRETE_INSTRUCTION(BitNot) 1869 1870 protected: 1871 virtual bool DataEquals(HValue* other) { return true; } 1872 }; 1873 1874 1875 class HUnaryMathOperation: public HTemplateInstruction<2> { 1876 public: 1877 HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op) 1878 : op_(op) { 1879 SetOperandAt(0, context); 1880 SetOperandAt(1, value); 1881 switch (op) { 1882 case kMathFloor: 1883 case kMathRound: 1884 case kMathCeil: 1885 set_representation(Representation::Integer32()); 1886 break; 1887 case kMathAbs: 1888 set_representation(Representation::Tagged()); 1889 SetFlag(kFlexibleRepresentation); 1890 break; 1891 case kMathSqrt: 1892 case kMathPowHalf: 1893 case kMathLog: 1894 case kMathSin: 1895 case kMathCos: 1896 case kMathTan: 1897 set_representation(Representation::Double()); 1898 break; 1899 default: 1900 UNREACHABLE(); 1901 } 1902 SetFlag(kUseGVN); 1903 } 1904 1905 HValue* context() { return OperandAt(0); } 1906 HValue* value() { return OperandAt(1); } 1907 1908 virtual void PrintDataTo(StringStream* stream); 1909 1910 virtual HType CalculateInferredType(); 1911 1912 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); 1913 1914 virtual Representation RequiredInputRepresentation(int index) { 1915 if (index == 0) { 1916 return Representation::Tagged(); 1917 } else { 1918 switch (op_) { 1919 case kMathFloor: 1920 case kMathRound: 1921 case kMathCeil: 1922 case kMathSqrt: 1923 case kMathPowHalf: 1924 case kMathLog: 1925 case kMathSin: 1926 case kMathCos: 1927 case kMathTan: 1928 return Representation::Double(); 1929 case kMathAbs: 1930 return representation(); 1931 default: 1932 UNREACHABLE(); 1933 return Representation::None(); 1934 } 1935 } 1936 } 1937 1938 virtual HValue* Canonicalize() { 1939 // If the input is integer32 then we replace the floor instruction 1940 // with its inputs. This happens before the representation changes are 1941 // introduced. 1942 if (op() == kMathFloor) { 1943 if (value()->representation().IsInteger32()) return value(); 1944 } 1945 return this; 1946 } 1947 1948 BuiltinFunctionId op() const { return op_; } 1949 const char* OpName() const; 1950 1951 DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation) 1952 1953 protected: 1954 virtual bool DataEquals(HValue* other) { 1955 HUnaryMathOperation* b = HUnaryMathOperation::cast(other); 1956 return op_ == b->op(); 1957 } 1958 1959 private: 1960 BuiltinFunctionId op_; 1961 }; 1962 1963 1964 class HLoadElements: public HUnaryOperation { 1965 public: 1966 explicit HLoadElements(HValue* value) : HUnaryOperation(value) { 1967 set_representation(Representation::Tagged()); 1968 SetFlag(kUseGVN); 1969 SetGVNFlag(kDependsOnElementsPointer); 1970 } 1971 1972 virtual Representation RequiredInputRepresentation(int index) { 1973 return Representation::Tagged(); 1974 } 1975 1976 DECLARE_CONCRETE_INSTRUCTION(LoadElements) 1977 1978 protected: 1979 virtual bool DataEquals(HValue* other) { return true; } 1980 }; 1981 1982 1983 class HLoadExternalArrayPointer: public HUnaryOperation { 1984 public: 1985 explicit HLoadExternalArrayPointer(HValue* value) 1986 : HUnaryOperation(value) { 1987 set_representation(Representation::External()); 1988 // The result of this instruction is idempotent as long as its inputs don't 1989 // change. The external array of a specialized array elements object cannot 1990 // change once set, so it's no necessary to introduce any additional 1991 // dependencies on top of the inputs. 1992 SetFlag(kUseGVN); 1993 } 1994 1995 virtual Representation RequiredInputRepresentation(int index) { 1996 return Representation::Tagged(); 1997 } 1998 1999 DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer) 2000 2001 protected: 2002 virtual bool DataEquals(HValue* other) { return true; } 2003 }; 2004 2005 2006 class HCheckMap: public HTemplateInstruction<2> { 2007 public: 2008 HCheckMap(HValue* value, 2009 Handle<Map> map, 2010 HValue* typecheck = NULL, 2011 CompareMapMode mode = REQUIRE_EXACT_MAP) 2012 : map_(map), 2013 mode_(mode) { 2014 SetOperandAt(0, value); 2015 // If callers don't depend on a typecheck, they can pass in NULL. In that 2016 // case we use a copy of the |value| argument as a dummy value. 2017 SetOperandAt(1, typecheck != NULL ? typecheck : value); 2018 set_representation(Representation::Tagged()); 2019 SetFlag(kUseGVN); 2020 SetGVNFlag(kDependsOnMaps); 2021 // If the map to check doesn't have the untransitioned elements, it must not 2022 // be hoisted above TransitionElements instructions. 2023 if (mode == REQUIRE_EXACT_MAP || !map->has_fast_smi_only_elements()) { 2024 SetGVNFlag(kDependsOnElementsKind); 2025 } 2026 has_element_transitions_ = 2027 map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL) != NULL || 2028 map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL) != NULL; 2029 } 2030 2031 virtual Representation RequiredInputRepresentation(int index) { 2032 return Representation::Tagged(); 2033 } 2034 virtual void PrintDataTo(StringStream* stream); 2035 virtual HType CalculateInferredType(); 2036 2037 HValue* value() { return OperandAt(0); } 2038 Handle<Map> map() const { return map_; } 2039 CompareMapMode mode() const { return mode_; } 2040 2041 DECLARE_CONCRETE_INSTRUCTION(CheckMap) 2042 2043 protected: 2044 virtual bool DataEquals(HValue* other) { 2045 HCheckMap* b = HCheckMap::cast(other); 2046 // Two CheckMaps instructions are DataEqual if their maps are identical and 2047 // they have the same mode. The mode comparison can be ignored if the map 2048 // has no elements transitions. 2049 return map_.is_identical_to(b->map()) && 2050 (b->mode() == mode() || !has_element_transitions_); 2051 } 2052 2053 private: 2054 bool has_element_transitions_; 2055 Handle<Map> map_; 2056 CompareMapMode mode_; 2057 }; 2058 2059 2060 class HCheckFunction: public HUnaryOperation { 2061 public: 2062 HCheckFunction(HValue* value, Handle<JSFunction> function) 2063 : HUnaryOperation(value), target_(function) { 2064 set_representation(Representation::Tagged()); 2065 SetFlag(kUseGVN); 2066 } 2067 2068 virtual Representation RequiredInputRepresentation(int index) { 2069 return Representation::Tagged(); 2070 } 2071 virtual void PrintDataTo(StringStream* stream); 2072 virtual HType CalculateInferredType(); 2073 2074 #ifdef DEBUG 2075 virtual void Verify(); 2076 #endif 2077 2078 Handle<JSFunction> target() const { return target_; } 2079 2080 DECLARE_CONCRETE_INSTRUCTION(CheckFunction) 2081 2082 protected: 2083 virtual bool DataEquals(HValue* other) { 2084 HCheckFunction* b = HCheckFunction::cast(other); 2085 return target_.is_identical_to(b->target()); 2086 } 2087 2088 private: 2089 Handle<JSFunction> target_; 2090 }; 2091 2092 2093 class HCheckInstanceType: public HUnaryOperation { 2094 public: 2095 static HCheckInstanceType* NewIsSpecObject(HValue* value) { 2096 return new HCheckInstanceType(value, IS_SPEC_OBJECT); 2097 } 2098 static HCheckInstanceType* NewIsJSArray(HValue* value) { 2099 return new HCheckInstanceType(value, IS_JS_ARRAY); 2100 } 2101 static HCheckInstanceType* NewIsString(HValue* value) { 2102 return new HCheckInstanceType(value, IS_STRING); 2103 } 2104 static HCheckInstanceType* NewIsSymbol(HValue* value) { 2105 return new HCheckInstanceType(value, IS_SYMBOL); 2106 } 2107 2108 virtual void PrintDataTo(StringStream* stream); 2109 2110 virtual Representation RequiredInputRepresentation(int index) { 2111 return Representation::Tagged(); 2112 } 2113 2114 virtual HValue* Canonicalize(); 2115 2116 bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; } 2117 void GetCheckInterval(InstanceType* first, InstanceType* last); 2118 void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag); 2119 2120 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType) 2121 2122 protected: 2123 // TODO(ager): It could be nice to allow the ommision of instance 2124 // type checks if we have already performed an instance type check 2125 // with a larger range. 2126 virtual bool DataEquals(HValue* other) { 2127 HCheckInstanceType* b = HCheckInstanceType::cast(other); 2128 return check_ == b->check_; 2129 } 2130 2131 private: 2132 enum Check { 2133 IS_SPEC_OBJECT, 2134 IS_JS_ARRAY, 2135 IS_STRING, 2136 IS_SYMBOL, 2137 LAST_INTERVAL_CHECK = IS_JS_ARRAY 2138 }; 2139 2140 const char* GetCheckName(); 2141 2142 HCheckInstanceType(HValue* value, Check check) 2143 : HUnaryOperation(value), check_(check) { 2144 set_representation(Representation::Tagged()); 2145 SetFlag(kUseGVN); 2146 } 2147 2148 const Check check_; 2149 }; 2150 2151 2152 class HCheckNonSmi: public HUnaryOperation { 2153 public: 2154 explicit HCheckNonSmi(HValue* value) : HUnaryOperation(value) { 2155 set_representation(Representation::Tagged()); 2156 SetFlag(kUseGVN); 2157 } 2158 2159 virtual Representation RequiredInputRepresentation(int index) { 2160 return Representation::Tagged(); 2161 } 2162 2163 virtual HType CalculateInferredType(); 2164 2165 #ifdef DEBUG 2166 virtual void Verify(); 2167 #endif 2168 2169 virtual HValue* Canonicalize() { 2170 HType value_type = value()->type(); 2171 if (!value_type.IsUninitialized() && 2172 (value_type.IsHeapNumber() || 2173 value_type.IsString() || 2174 value_type.IsBoolean() || 2175 value_type.IsNonPrimitive())) { 2176 return NULL; 2177 } 2178 return this; 2179 } 2180 2181 DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi) 2182 2183 protected: 2184 virtual bool DataEquals(HValue* other) { return true; } 2185 }; 2186 2187 2188 class HCheckPrototypeMaps: public HTemplateInstruction<0> { 2189 public: 2190 HCheckPrototypeMaps(Handle<JSObject> prototype, Handle<JSObject> holder) 2191 : prototype_(prototype), holder_(holder) { 2192 SetFlag(kUseGVN); 2193 SetGVNFlag(kDependsOnMaps); 2194 } 2195 2196 #ifdef DEBUG 2197 virtual void Verify(); 2198 #endif 2199 2200 Handle<JSObject> prototype() const { return prototype_; } 2201 Handle<JSObject> holder() const { return holder_; } 2202 2203 DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps) 2204 2205 virtual Representation RequiredInputRepresentation(int index) { 2206 return Representation::None(); 2207 } 2208 2209 virtual intptr_t Hashcode() { 2210 ASSERT(!HEAP->IsAllocationAllowed()); 2211 intptr_t hash = reinterpret_cast<intptr_t>(*prototype()); 2212 hash = 17 * hash + reinterpret_cast<intptr_t>(*holder()); 2213 return hash; 2214 } 2215 2216 protected: 2217 virtual bool DataEquals(HValue* other) { 2218 HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other); 2219 return prototype_.is_identical_to(b->prototype()) && 2220 holder_.is_identical_to(b->holder()); 2221 } 2222 2223 private: 2224 Handle<JSObject> prototype_; 2225 Handle<JSObject> holder_; 2226 }; 2227 2228 2229 class HCheckSmi: public HUnaryOperation { 2230 public: 2231 explicit HCheckSmi(HValue* value) : HUnaryOperation(value) { 2232 set_representation(Representation::Tagged()); 2233 SetFlag(kUseGVN); 2234 } 2235 2236 virtual Representation RequiredInputRepresentation(int index) { 2237 return Representation::Tagged(); 2238 } 2239 virtual HType CalculateInferredType(); 2240 2241 #ifdef DEBUG 2242 virtual void Verify(); 2243 #endif 2244 2245 DECLARE_CONCRETE_INSTRUCTION(CheckSmi) 2246 2247 protected: 2248 virtual bool DataEquals(HValue* other) { return true; } 2249 }; 2250 2251 2252 class HPhi: public HValue { 2253 public: 2254 explicit HPhi(int merged_index) 2255 : inputs_(2), 2256 merged_index_(merged_index), 2257 phi_id_(-1), 2258 is_live_(false), 2259 is_convertible_to_integer_(true) { 2260 for (int i = 0; i < Representation::kNumRepresentations; i++) { 2261 non_phi_uses_[i] = 0; 2262 indirect_uses_[i] = 0; 2263 } 2264 ASSERT(merged_index >= 0); 2265 set_representation(Representation::Tagged()); 2266 SetFlag(kFlexibleRepresentation); 2267 } 2268 2269 virtual Representation InferredRepresentation(); 2270 2271 virtual Range* InferRange(Zone* zone); 2272 virtual Representation RequiredInputRepresentation(int index) { 2273 return representation(); 2274 } 2275 virtual HType CalculateInferredType(); 2276 virtual int OperandCount() { return inputs_.length(); } 2277 virtual HValue* OperandAt(int index) { return inputs_[index]; } 2278 HValue* GetRedundantReplacement(); 2279 void AddInput(HValue* value); 2280 bool HasRealUses(); 2281 2282 bool IsReceiver() { return merged_index_ == 0; } 2283 2284 int merged_index() const { return merged_index_; } 2285 2286 virtual void PrintTo(StringStream* stream); 2287 2288 #ifdef DEBUG 2289 virtual void Verify(); 2290 #endif 2291 2292 void InitRealUses(int id); 2293 void AddNonPhiUsesFrom(HPhi* other); 2294 void AddIndirectUsesTo(int* use_count); 2295 2296 int tagged_non_phi_uses() const { 2297 return non_phi_uses_[Representation::kTagged]; 2298 } 2299 int int32_non_phi_uses() const { 2300 return non_phi_uses_[Representation::kInteger32]; 2301 } 2302 int double_non_phi_uses() const { 2303 return non_phi_uses_[Representation::kDouble]; 2304 } 2305 int tagged_indirect_uses() const { 2306 return indirect_uses_[Representation::kTagged]; 2307 } 2308 int int32_indirect_uses() const { 2309 return indirect_uses_[Representation::kInteger32]; 2310 } 2311 int double_indirect_uses() const { 2312 return indirect_uses_[Representation::kDouble]; 2313 } 2314 int phi_id() { return phi_id_; } 2315 bool is_live() { return is_live_; } 2316 void set_is_live(bool b) { is_live_ = b; } 2317 2318 static HPhi* cast(HValue* value) { 2319 ASSERT(value->IsPhi()); 2320 return reinterpret_cast<HPhi*>(value); 2321 } 2322 virtual Opcode opcode() const { return HValue::kPhi; } 2323 2324 virtual bool IsConvertibleToInteger() const { 2325 return is_convertible_to_integer_; 2326 } 2327 2328 void set_is_convertible_to_integer(bool b) { 2329 is_convertible_to_integer_ = b; 2330 } 2331 2332 bool AllOperandsConvertibleToInteger() { 2333 for (int i = 0; i < OperandCount(); ++i) { 2334 if (!OperandAt(i)->IsConvertibleToInteger()) return false; 2335 } 2336 return true; 2337 } 2338 2339 protected: 2340 virtual void DeleteFromGraph(); 2341 virtual void InternalSetOperandAt(int index, HValue* value) { 2342 inputs_[index] = value; 2343 } 2344 2345 private: 2346 ZoneList<HValue*> inputs_; 2347 int merged_index_; 2348 2349 int non_phi_uses_[Representation::kNumRepresentations]; 2350 int indirect_uses_[Representation::kNumRepresentations]; 2351 int phi_id_; 2352 bool is_live_; 2353 bool is_convertible_to_integer_; 2354 }; 2355 2356 2357 class HArgumentsObject: public HTemplateInstruction<0> { 2358 public: 2359 HArgumentsObject() { 2360 set_representation(Representation::Tagged()); 2361 SetFlag(kIsArguments); 2362 } 2363 2364 virtual Representation RequiredInputRepresentation(int index) { 2365 return Representation::None(); 2366 } 2367 2368 DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject) 2369 }; 2370 2371 2372 class HConstant: public HTemplateInstruction<0> { 2373 public: 2374 HConstant(Handle<Object> handle, Representation r); 2375 2376 Handle<Object> handle() const { return handle_; } 2377 2378 bool InOldSpace() const { return !HEAP->InNewSpace(*handle_); } 2379 2380 bool ImmortalImmovable() const { 2381 Heap* heap = HEAP; 2382 if (*handle_ == heap->undefined_value()) return true; 2383 if (*handle_ == heap->null_value()) return true; 2384 if (*handle_ == heap->true_value()) return true; 2385 if (*handle_ == heap->false_value()) return true; 2386 if (*handle_ == heap->the_hole_value()) return true; 2387 if (*handle_ == heap->minus_zero_value()) return true; 2388 if (*handle_ == heap->nan_value()) return true; 2389 if (*handle_ == heap->empty_string()) return true; 2390 return false; 2391 } 2392 2393 virtual Representation RequiredInputRepresentation(int index) { 2394 return Representation::None(); 2395 } 2396 2397 virtual bool IsConvertibleToInteger() const { 2398 if (handle_->IsSmi()) return true; 2399 if (handle_->IsHeapNumber() && 2400 (HeapNumber::cast(*handle_)->value() == 2401 static_cast<double>(NumberToInt32(*handle_)))) return true; 2402 return false; 2403 } 2404 2405 virtual bool EmitAtUses() { return !representation().IsDouble(); } 2406 virtual HValue* Canonicalize(); 2407 virtual void PrintDataTo(StringStream* stream); 2408 virtual HType CalculateInferredType(); 2409 bool IsInteger() const { return handle_->IsSmi(); } 2410 HConstant* CopyToRepresentation(Representation r) const; 2411 HConstant* CopyToTruncatedInt32() const; 2412 bool HasInteger32Value() const { return has_int32_value_; } 2413 int32_t Integer32Value() const { 2414 ASSERT(HasInteger32Value()); 2415 return int32_value_; 2416 } 2417 bool HasDoubleValue() const { return has_double_value_; } 2418 double DoubleValue() const { 2419 ASSERT(HasDoubleValue()); 2420 return double_value_; 2421 } 2422 bool HasNumberValue() const { return has_int32_value_ || has_double_value_; } 2423 int32_t NumberValueAsInteger32() const { 2424 ASSERT(HasNumberValue()); 2425 if (has_int32_value_) return int32_value_; 2426 return DoubleToInt32(double_value_); 2427 } 2428 bool HasStringValue() const { return handle_->IsString(); } 2429 2430 bool ToBoolean() const; 2431 2432 virtual intptr_t Hashcode() { 2433 ASSERT(!HEAP->allow_allocation(false)); 2434 intptr_t hash = reinterpret_cast<intptr_t>(*handle()); 2435 // Prevent smis from having fewer hash values when truncated to 2436 // the least significant bits. 2437 const int kShiftSize = kSmiShiftSize + kSmiTagSize; 2438 STATIC_ASSERT(kShiftSize != 0); 2439 return hash ^ (hash >> kShiftSize); 2440 } 2441 2442 #ifdef DEBUG 2443 virtual void Verify() { } 2444 #endif 2445 2446 DECLARE_CONCRETE_INSTRUCTION(Constant) 2447 2448 protected: 2449 virtual Range* InferRange(Zone* zone); 2450 2451 virtual bool DataEquals(HValue* other) { 2452 HConstant* other_constant = HConstant::cast(other); 2453 return handle().is_identical_to(other_constant->handle()); 2454 } 2455 2456 private: 2457 Handle<Object> handle_; 2458 2459 // The following two values represent the int32 and the double value of the 2460 // given constant if there is a lossless conversion between the constant 2461 // and the specific representation. 2462 bool has_int32_value_ : 1; 2463 bool has_double_value_ : 1; 2464 int32_t int32_value_; 2465 double double_value_; 2466 }; 2467 2468 2469 class HBinaryOperation: public HTemplateInstruction<3> { 2470 public: 2471 HBinaryOperation(HValue* context, HValue* left, HValue* right) { 2472 ASSERT(left != NULL && right != NULL); 2473 SetOperandAt(0, context); 2474 SetOperandAt(1, left); 2475 SetOperandAt(2, right); 2476 } 2477 2478 HValue* context() { return OperandAt(0); } 2479 HValue* left() { return OperandAt(1); } 2480 HValue* right() { return OperandAt(2); } 2481 2482 // TODO(kasperl): Move these helpers to the IA-32 Lithium 2483 // instruction sequence builder. 2484 HValue* LeastConstantOperand() { 2485 if (IsCommutative() && left()->IsConstant()) return right(); 2486 return left(); 2487 } 2488 HValue* MostConstantOperand() { 2489 if (IsCommutative() && left()->IsConstant()) return left(); 2490 return right(); 2491 } 2492 2493 virtual bool IsCommutative() const { return false; } 2494 2495 virtual void PrintDataTo(StringStream* stream); 2496 }; 2497 2498 2499 class HWrapReceiver: public HTemplateInstruction<2> { 2500 public: 2501 HWrapReceiver(HValue* receiver, HValue* function) { 2502 set_representation(Representation::Tagged()); 2503 SetOperandAt(0, receiver); 2504 SetOperandAt(1, function); 2505 } 2506 2507 virtual Representation RequiredInputRepresentation(int index) { 2508 return Representation::Tagged(); 2509 } 2510 2511 HValue* receiver() { return OperandAt(0); } 2512 HValue* function() { return OperandAt(1); } 2513 2514 virtual HValue* Canonicalize(); 2515 2516 DECLARE_CONCRETE_INSTRUCTION(WrapReceiver) 2517 }; 2518 2519 2520 class HApplyArguments: public HTemplateInstruction<4> { 2521 public: 2522 HApplyArguments(HValue* function, 2523 HValue* receiver, 2524 HValue* length, 2525 HValue* elements) { 2526 set_representation(Representation::Tagged()); 2527 SetOperandAt(0, function); 2528 SetOperandAt(1, receiver); 2529 SetOperandAt(2, length); 2530 SetOperandAt(3, elements); 2531 SetAllSideEffects(); 2532 } 2533 2534 virtual Representation RequiredInputRepresentation(int index) { 2535 // The length is untagged, all other inputs are tagged. 2536 return (index == 2) 2537 ? Representation::Integer32() 2538 : Representation::Tagged(); 2539 } 2540 2541 HValue* function() { return OperandAt(0); } 2542 HValue* receiver() { return OperandAt(1); } 2543 HValue* length() { return OperandAt(2); } 2544 HValue* elements() { return OperandAt(3); } 2545 2546 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments) 2547 }; 2548 2549 2550 class HArgumentsElements: public HTemplateInstruction<0> { 2551 public: 2552 HArgumentsElements() { 2553 // The value produced by this instruction is a pointer into the stack 2554 // that looks as if it was a smi because of alignment. 2555 set_representation(Representation::Tagged()); 2556 SetFlag(kUseGVN); 2557 } 2558 2559 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements) 2560 2561 virtual Representation RequiredInputRepresentation(int index) { 2562 return Representation::None(); 2563 } 2564 2565 protected: 2566 virtual bool DataEquals(HValue* other) { return true; } 2567 }; 2568 2569 2570 class HArgumentsLength: public HUnaryOperation { 2571 public: 2572 explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) { 2573 set_representation(Representation::Integer32()); 2574 SetFlag(kUseGVN); 2575 } 2576 2577 virtual Representation RequiredInputRepresentation(int index) { 2578 return Representation::Tagged(); 2579 } 2580 2581 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength) 2582 2583 protected: 2584 virtual bool DataEquals(HValue* other) { return true; } 2585 }; 2586 2587 2588 class HAccessArgumentsAt: public HTemplateInstruction<3> { 2589 public: 2590 HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) { 2591 set_representation(Representation::Tagged()); 2592 SetFlag(kUseGVN); 2593 SetOperandAt(0, arguments); 2594 SetOperandAt(1, length); 2595 SetOperandAt(2, index); 2596 } 2597 2598 virtual void PrintDataTo(StringStream* stream); 2599 2600 virtual Representation RequiredInputRepresentation(int index) { 2601 // The arguments elements is considered tagged. 2602 return index == 0 2603 ? Representation::Tagged() 2604 : Representation::Integer32(); 2605 } 2606 2607 HValue* arguments() { return OperandAt(0); } 2608 HValue* length() { return OperandAt(1); } 2609 HValue* index() { return OperandAt(2); } 2610 2611 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt) 2612 2613 virtual bool DataEquals(HValue* other) { return true; } 2614 }; 2615 2616 2617 class HBoundsCheck: public HTemplateInstruction<2> { 2618 public: 2619 HBoundsCheck(HValue* index, HValue* length) { 2620 SetOperandAt(0, index); 2621 SetOperandAt(1, length); 2622 set_representation(Representation::Integer32()); 2623 SetFlag(kUseGVN); 2624 } 2625 2626 virtual Representation RequiredInputRepresentation(int index) { 2627 return Representation::Integer32(); 2628 } 2629 2630 virtual void PrintDataTo(StringStream* stream); 2631 2632 HValue* index() { return OperandAt(0); } 2633 HValue* length() { return OperandAt(1); } 2634 2635 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) 2636 2637 protected: 2638 virtual bool DataEquals(HValue* other) { return true; } 2639 }; 2640 2641 2642 class HBitwiseBinaryOperation: public HBinaryOperation { 2643 public: 2644 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right) 2645 : HBinaryOperation(context, left, right) { 2646 set_representation(Representation::Tagged()); 2647 SetFlag(kFlexibleRepresentation); 2648 SetAllSideEffects(); 2649 } 2650 2651 virtual Representation RequiredInputRepresentation(int index) { 2652 return index == 0 2653 ? Representation::Tagged() 2654 : representation(); 2655 } 2656 2657 virtual void RepresentationChanged(Representation to) { 2658 if (!to.IsTagged()) { 2659 ASSERT(to.IsInteger32()); 2660 ClearAllSideEffects(); 2661 SetFlag(kTruncatingToInt32); 2662 SetFlag(kUseGVN); 2663 } 2664 } 2665 2666 virtual HType CalculateInferredType(); 2667 2668 DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation) 2669 }; 2670 2671 2672 class HArithmeticBinaryOperation: public HBinaryOperation { 2673 public: 2674 HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right) 2675 : HBinaryOperation(context, left, right) { 2676 set_representation(Representation::Tagged()); 2677 SetFlag(kFlexibleRepresentation); 2678 SetAllSideEffects(); 2679 } 2680 2681 virtual void RepresentationChanged(Representation to) { 2682 if (!to.IsTagged()) { 2683 ClearAllSideEffects(); 2684 SetFlag(kUseGVN); 2685 } 2686 } 2687 2688 virtual HType CalculateInferredType(); 2689 virtual Representation RequiredInputRepresentation(int index) { 2690 return index == 0 2691 ? Representation::Tagged() 2692 : representation(); 2693 } 2694 2695 virtual Representation InferredRepresentation() { 2696 if (left()->representation().Equals(right()->representation())) { 2697 return left()->representation(); 2698 } 2699 return HValue::InferredRepresentation(); 2700 } 2701 }; 2702 2703 2704 class HCompareGeneric: public HBinaryOperation { 2705 public: 2706 HCompareGeneric(HValue* context, 2707 HValue* left, 2708 HValue* right, 2709 Token::Value token) 2710 : HBinaryOperation(context, left, right), token_(token) { 2711 ASSERT(Token::IsCompareOp(token)); 2712 set_representation(Representation::Tagged()); 2713 SetAllSideEffects(); 2714 } 2715 2716 virtual Representation RequiredInputRepresentation(int index) { 2717 return Representation::Tagged(); 2718 } 2719 2720 Representation GetInputRepresentation() const { 2721 return Representation::Tagged(); 2722 } 2723 2724 Token::Value token() const { return token_; } 2725 virtual void PrintDataTo(StringStream* stream); 2726 2727 virtual HType CalculateInferredType(); 2728 2729 DECLARE_CONCRETE_INSTRUCTION(CompareGeneric) 2730 2731 private: 2732 Token::Value token_; 2733 }; 2734 2735 2736 class HCompareIDAndBranch: public HTemplateControlInstruction<2, 2> { 2737 public: 2738 HCompareIDAndBranch(HValue* left, HValue* right, Token::Value token) 2739 : token_(token) { 2740 ASSERT(Token::IsCompareOp(token)); 2741 SetOperandAt(0, left); 2742 SetOperandAt(1, right); 2743 } 2744 2745 HValue* left() { return OperandAt(0); } 2746 HValue* right() { return OperandAt(1); } 2747 Token::Value token() const { return token_; } 2748 2749 void SetInputRepresentation(Representation r); 2750 Representation GetInputRepresentation() const { 2751 return input_representation_; 2752 } 2753 2754 virtual Representation RequiredInputRepresentation(int index) { 2755 return input_representation_; 2756 } 2757 virtual void PrintDataTo(StringStream* stream); 2758 2759 DECLARE_CONCRETE_INSTRUCTION(CompareIDAndBranch) 2760 2761 private: 2762 Representation input_representation_; 2763 Token::Value token_; 2764 }; 2765 2766 2767 class HCompareObjectEqAndBranch: public HTemplateControlInstruction<2, 2> { 2768 public: 2769 HCompareObjectEqAndBranch(HValue* left, HValue* right) { 2770 SetOperandAt(0, left); 2771 SetOperandAt(1, right); 2772 } 2773 2774 HValue* left() { return OperandAt(0); } 2775 HValue* right() { return OperandAt(1); } 2776 2777 virtual void PrintDataTo(StringStream* stream); 2778 2779 virtual Representation RequiredInputRepresentation(int index) { 2780 return Representation::Tagged(); 2781 } 2782 2783 DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch) 2784 }; 2785 2786 2787 class HCompareConstantEqAndBranch: public HUnaryControlInstruction { 2788 public: 2789 HCompareConstantEqAndBranch(HValue* left, int right, Token::Value op) 2790 : HUnaryControlInstruction(left, NULL, NULL), op_(op), right_(right) { 2791 ASSERT(op == Token::EQ_STRICT); 2792 } 2793 2794 Token::Value op() const { return op_; } 2795 HValue* left() { return value(); } 2796 int right() const { return right_; } 2797 2798 virtual Representation RequiredInputRepresentation(int index) { 2799 return Representation::Integer32(); 2800 } 2801 2802 DECLARE_CONCRETE_INSTRUCTION(CompareConstantEqAndBranch); 2803 2804 private: 2805 const Token::Value op_; 2806 const int right_; 2807 }; 2808 2809 2810 class HIsNilAndBranch: public HUnaryControlInstruction { 2811 public: 2812 HIsNilAndBranch(HValue* value, EqualityKind kind, NilValue nil) 2813 : HUnaryControlInstruction(value, NULL, NULL), kind_(kind), nil_(nil) { } 2814 2815 EqualityKind kind() const { return kind_; } 2816 NilValue nil() const { return nil_; } 2817 2818 virtual void PrintDataTo(StringStream* stream); 2819 2820 virtual Representation RequiredInputRepresentation(int index) { 2821 return Representation::Tagged(); 2822 } 2823 2824 DECLARE_CONCRETE_INSTRUCTION(IsNilAndBranch) 2825 2826 private: 2827 EqualityKind kind_; 2828 NilValue nil_; 2829 }; 2830 2831 2832 class HIsObjectAndBranch: public HUnaryControlInstruction { 2833 public: 2834 explicit HIsObjectAndBranch(HValue* value) 2835 : HUnaryControlInstruction(value, NULL, NULL) { } 2836 2837 virtual Representation RequiredInputRepresentation(int index) { 2838 return Representation::Tagged(); 2839 } 2840 2841 DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch) 2842 }; 2843 2844 class HIsStringAndBranch: public HUnaryControlInstruction { 2845 public: 2846 explicit HIsStringAndBranch(HValue* value) 2847 : HUnaryControlInstruction(value, NULL, NULL) { } 2848 2849 virtual Representation RequiredInputRepresentation(int index) { 2850 return Representation::Tagged(); 2851 } 2852 2853 DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch) 2854 }; 2855 2856 2857 class HIsSmiAndBranch: public HUnaryControlInstruction { 2858 public: 2859 explicit HIsSmiAndBranch(HValue* value) 2860 : HUnaryControlInstruction(value, NULL, NULL) { } 2861 2862 DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch) 2863 2864 virtual Representation RequiredInputRepresentation(int index) { 2865 return Representation::Tagged(); 2866 } 2867 2868 protected: 2869 virtual bool DataEquals(HValue* other) { return true; } 2870 }; 2871 2872 2873 class HIsUndetectableAndBranch: public HUnaryControlInstruction { 2874 public: 2875 explicit HIsUndetectableAndBranch(HValue* value) 2876 : HUnaryControlInstruction(value, NULL, NULL) { } 2877 2878 virtual Representation RequiredInputRepresentation(int index) { 2879 return Representation::Tagged(); 2880 } 2881 2882 DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch) 2883 }; 2884 2885 2886 class HStringCompareAndBranch: public HTemplateControlInstruction<2, 3> { 2887 public: 2888 HStringCompareAndBranch(HValue* context, 2889 HValue* left, 2890 HValue* right, 2891 Token::Value token) 2892 : token_(token) { 2893 ASSERT(Token::IsCompareOp(token)); 2894 SetOperandAt(0, context); 2895 SetOperandAt(1, left); 2896 SetOperandAt(2, right); 2897 set_representation(Representation::Tagged()); 2898 } 2899 2900 HValue* context() { return OperandAt(0); } 2901 HValue* left() { return OperandAt(1); } 2902 HValue* right() { return OperandAt(2); } 2903 Token::Value token() const { return token_; } 2904 2905 virtual void PrintDataTo(StringStream* stream); 2906 2907 virtual Representation RequiredInputRepresentation(int index) { 2908 return Representation::Tagged(); 2909 } 2910 2911 Representation GetInputRepresentation() const { 2912 return Representation::Tagged(); 2913 } 2914 2915 DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch) 2916 2917 private: 2918 Token::Value token_; 2919 }; 2920 2921 2922 class HIsConstructCallAndBranch: public HTemplateControlInstruction<2, 0> { 2923 public: 2924 virtual Representation RequiredInputRepresentation(int index) { 2925 return Representation::None(); 2926 } 2927 2928 DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch) 2929 }; 2930 2931 2932 class HHasInstanceTypeAndBranch: public HUnaryControlInstruction { 2933 public: 2934 HHasInstanceTypeAndBranch(HValue* value, InstanceType type) 2935 : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { } 2936 HHasInstanceTypeAndBranch(HValue* value, InstanceType from, InstanceType to) 2937 : HUnaryControlInstruction(value, NULL, NULL), from_(from), to_(to) { 2938 ASSERT(to == LAST_TYPE); // Others not implemented yet in backend. 2939 } 2940 2941 InstanceType from() { return from_; } 2942 InstanceType to() { return to_; } 2943 2944 virtual void PrintDataTo(StringStream* stream); 2945 2946 virtual Representation RequiredInputRepresentation(int index) { 2947 return Representation::Tagged(); 2948 } 2949 2950 DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch) 2951 2952 private: 2953 InstanceType from_; 2954 InstanceType to_; // Inclusive range, not all combinations work. 2955 }; 2956 2957 2958 class HHasCachedArrayIndexAndBranch: public HUnaryControlInstruction { 2959 public: 2960 explicit HHasCachedArrayIndexAndBranch(HValue* value) 2961 : HUnaryControlInstruction(value, NULL, NULL) { } 2962 2963 virtual Representation RequiredInputRepresentation(int index) { 2964 return Representation::Tagged(); 2965 } 2966 2967 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch) 2968 }; 2969 2970 2971 class HGetCachedArrayIndex: public HUnaryOperation { 2972 public: 2973 explicit HGetCachedArrayIndex(HValue* value) : HUnaryOperation(value) { 2974 set_representation(Representation::Tagged()); 2975 SetFlag(kUseGVN); 2976 } 2977 2978 virtual Representation RequiredInputRepresentation(int index) { 2979 return Representation::Tagged(); 2980 } 2981 2982 DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex) 2983 2984 protected: 2985 virtual bool DataEquals(HValue* other) { return true; } 2986 }; 2987 2988 2989 class HClassOfTestAndBranch: public HUnaryControlInstruction { 2990 public: 2991 HClassOfTestAndBranch(HValue* value, Handle<String> class_name) 2992 : HUnaryControlInstruction(value, NULL, NULL), 2993 class_name_(class_name) { } 2994 2995 DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch) 2996 2997 virtual Representation RequiredInputRepresentation(int index) { 2998 return Representation::Tagged(); 2999 } 3000 3001 virtual void PrintDataTo(StringStream* stream); 3002 3003 Handle<String> class_name() const { return class_name_; } 3004 3005 private: 3006 Handle<String> class_name_; 3007 }; 3008 3009 3010 class HTypeofIsAndBranch: public HUnaryControlInstruction { 3011 public: 3012 HTypeofIsAndBranch(HValue* value, Handle<String> type_literal) 3013 : HUnaryControlInstruction(value, NULL, NULL), 3014 type_literal_(type_literal) { } 3015 3016 Handle<String> type_literal() { return type_literal_; } 3017 virtual void PrintDataTo(StringStream* stream); 3018 3019 DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch) 3020 3021 virtual Representation RequiredInputRepresentation(int index) { 3022 return Representation::Tagged(); 3023 } 3024 3025 private: 3026 Handle<String> type_literal_; 3027 }; 3028 3029 3030 class HInstanceOf: public HBinaryOperation { 3031 public: 3032 HInstanceOf(HValue* context, HValue* left, HValue* right) 3033 : HBinaryOperation(context, left, right) { 3034 set_representation(Representation::Tagged()); 3035 SetAllSideEffects(); 3036 } 3037 3038 virtual Representation RequiredInputRepresentation(int index) { 3039 return Representation::Tagged(); 3040 } 3041 3042 virtual HType CalculateInferredType(); 3043 3044 virtual void PrintDataTo(StringStream* stream); 3045 3046 DECLARE_CONCRETE_INSTRUCTION(InstanceOf) 3047 }; 3048 3049 3050 class HInstanceOfKnownGlobal: public HTemplateInstruction<2> { 3051 public: 3052 HInstanceOfKnownGlobal(HValue* context, 3053 HValue* left, 3054 Handle<JSFunction> right) 3055 : function_(right) { 3056 SetOperandAt(0, context); 3057 SetOperandAt(1, left); 3058 set_representation(Representation::Tagged()); 3059 SetAllSideEffects(); 3060 } 3061 3062 HValue* context() { return OperandAt(0); } 3063 HValue* left() { return OperandAt(1); } 3064 Handle<JSFunction> function() { return function_; } 3065 3066 virtual Representation RequiredInputRepresentation(int index) { 3067 return Representation::Tagged(); 3068 } 3069 3070 virtual HType CalculateInferredType(); 3071 3072 DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal) 3073 3074 private: 3075 Handle<JSFunction> function_; 3076 }; 3077 3078 3079 class HPower: public HTemplateInstruction<2> { 3080 public: 3081 HPower(HValue* left, HValue* right) { 3082 SetOperandAt(0, left); 3083 SetOperandAt(1, right); 3084 set_representation(Representation::Double()); 3085 SetFlag(kUseGVN); 3086 } 3087 3088 HValue* left() { return OperandAt(0); } 3089 HValue* right() { return OperandAt(1); } 3090 3091 virtual Representation RequiredInputRepresentation(int index) { 3092 return index == 0 3093 ? Representation::Double() 3094 : Representation::None(); 3095 } 3096 3097 DECLARE_CONCRETE_INSTRUCTION(Power) 3098 3099 protected: 3100 virtual bool DataEquals(HValue* other) { return true; } 3101 }; 3102 3103 3104 class HRandom: public HTemplateInstruction<1> { 3105 public: 3106 explicit HRandom(HValue* global_object) { 3107 SetOperandAt(0, global_object); 3108 set_representation(Representation::Double()); 3109 } 3110 3111 HValue* global_object() { return OperandAt(0); } 3112 3113 virtual Representation RequiredInputRepresentation(int index) { 3114 return Representation::Tagged(); 3115 } 3116 3117 DECLARE_CONCRETE_INSTRUCTION(Random) 3118 }; 3119 3120 3121 class HAdd: public HArithmeticBinaryOperation { 3122 public: 3123 HAdd(HValue* context, HValue* left, HValue* right) 3124 : HArithmeticBinaryOperation(context, left, right) { 3125 SetFlag(kCanOverflow); 3126 } 3127 3128 // Add is only commutative if two integer values are added and not if two 3129 // tagged values are added (because it might be a String concatenation). 3130 virtual bool IsCommutative() const { 3131 return !representation().IsTagged(); 3132 } 3133 3134 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); 3135 3136 static HInstruction* NewHAdd(Zone* zone, 3137 HValue* context, 3138 HValue* left, 3139 HValue* right); 3140 3141 virtual HType CalculateInferredType(); 3142 3143 virtual HValue* Canonicalize(); 3144 3145 DECLARE_CONCRETE_INSTRUCTION(Add) 3146 3147 protected: 3148 virtual bool DataEquals(HValue* other) { return true; } 3149 3150 virtual Range* InferRange(Zone* zone); 3151 }; 3152 3153 3154 class HSub: public HArithmeticBinaryOperation { 3155 public: 3156 HSub(HValue* context, HValue* left, HValue* right) 3157 : HArithmeticBinaryOperation(context, left, right) { 3158 SetFlag(kCanOverflow); 3159 } 3160 3161 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); 3162 3163 virtual HValue* Canonicalize(); 3164 3165 static HInstruction* NewHSub(Zone* zone, 3166 HValue* context, 3167 HValue* left, 3168 HValue* right); 3169 3170 DECLARE_CONCRETE_INSTRUCTION(Sub) 3171 3172 protected: 3173 virtual bool DataEquals(HValue* other) { return true; } 3174 3175 virtual Range* InferRange(Zone* zone); 3176 }; 3177 3178 3179 class HMul: public HArithmeticBinaryOperation { 3180 public: 3181 HMul(HValue* context, HValue* left, HValue* right) 3182 : HArithmeticBinaryOperation(context, left, right) { 3183 SetFlag(kCanOverflow); 3184 } 3185 3186 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); 3187 3188 // Only commutative if it is certain that not two objects are multiplicated. 3189 virtual bool IsCommutative() const { 3190 return !representation().IsTagged(); 3191 } 3192 3193 static HInstruction* NewHMul(Zone* zone, 3194 HValue* context, 3195 HValue* left, 3196 HValue* right); 3197 3198 DECLARE_CONCRETE_INSTRUCTION(Mul) 3199 3200 protected: 3201 virtual bool DataEquals(HValue* other) { return true; } 3202 3203 virtual Range* InferRange(Zone* zone); 3204 }; 3205 3206 3207 class HMod: public HArithmeticBinaryOperation { 3208 public: 3209 HMod(HValue* context, HValue* left, HValue* right) 3210 : HArithmeticBinaryOperation(context, left, right) { 3211 SetFlag(kCanBeDivByZero); 3212 } 3213 3214 bool HasPowerOf2Divisor() { 3215 if (right()->IsConstant() && 3216 HConstant::cast(right())->HasInteger32Value()) { 3217 int32_t value = HConstant::cast(right())->Integer32Value(); 3218 return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value)); 3219 } 3220 3221 return false; 3222 } 3223 3224 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); 3225 3226 static HInstruction* NewHMod(Zone* zone, 3227 HValue* context, 3228 HValue* left, 3229 HValue* right); 3230 3231 DECLARE_CONCRETE_INSTRUCTION(Mod) 3232 3233 protected: 3234 virtual bool DataEquals(HValue* other) { return true; } 3235 3236 virtual Range* InferRange(Zone* zone); 3237 }; 3238 3239 3240 class HDiv: public HArithmeticBinaryOperation { 3241 public: 3242 HDiv(HValue* context, HValue* left, HValue* right) 3243 : HArithmeticBinaryOperation(context, left, right) { 3244 SetFlag(kCanBeDivByZero); 3245 SetFlag(kCanOverflow); 3246 } 3247 3248 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); 3249 3250 static HInstruction* NewHDiv(Zone* zone, 3251 HValue* context, 3252 HValue* left, 3253 HValue* right); 3254 3255 DECLARE_CONCRETE_INSTRUCTION(Div) 3256 3257 protected: 3258 virtual bool DataEquals(HValue* other) { return true; } 3259 3260 virtual Range* InferRange(Zone* zone); 3261 }; 3262 3263 3264 class HBitwise: public HBitwiseBinaryOperation { 3265 public: 3266 HBitwise(Token::Value op, HValue* context, HValue* left, HValue* right) 3267 : HBitwiseBinaryOperation(context, left, right), op_(op) { 3268 ASSERT(op == Token::BIT_AND || 3269 op == Token::BIT_OR || 3270 op == Token::BIT_XOR); 3271 } 3272 3273 Token::Value op() const { return op_; } 3274 3275 virtual bool IsCommutative() const { return true; } 3276 3277 virtual HValue* Canonicalize(); 3278 3279 static HInstruction* NewHBitwise(Zone* zone, 3280 Token::Value op, 3281 HValue* context, 3282 HValue* left, 3283 HValue* right); 3284 3285 DECLARE_CONCRETE_INSTRUCTION(Bitwise) 3286 3287 protected: 3288 virtual bool DataEquals(HValue* other) { 3289 return op() == HBitwise::cast(other)->op(); 3290 } 3291 3292 virtual Range* InferRange(Zone* zone); 3293 3294 private: 3295 Token::Value op_; 3296 }; 3297 3298 3299 class HShl: public HBitwiseBinaryOperation { 3300 public: 3301 HShl(HValue* context, HValue* left, HValue* right) 3302 : HBitwiseBinaryOperation(context, left, right) { } 3303 3304 virtual Range* InferRange(Zone* zone); 3305 3306 static HInstruction* NewHShl(Zone* zone, 3307 HValue* context, 3308 HValue* left, 3309 HValue* right); 3310 3311 DECLARE_CONCRETE_INSTRUCTION(Shl) 3312 3313 protected: 3314 virtual bool DataEquals(HValue* other) { return true; } 3315 }; 3316 3317 3318 class HShr: public HBitwiseBinaryOperation { 3319 public: 3320 HShr(HValue* context, HValue* left, HValue* right) 3321 : HBitwiseBinaryOperation(context, left, right) { } 3322 3323 virtual Range* InferRange(Zone* zone); 3324 3325 static HInstruction* NewHShr(Zone* zone, 3326 HValue* context, 3327 HValue* left, 3328 HValue* right); 3329 3330 DECLARE_CONCRETE_INSTRUCTION(Shr) 3331 3332 protected: 3333 virtual bool DataEquals(HValue* other) { return true; } 3334 }; 3335 3336 3337 class HSar: public HBitwiseBinaryOperation { 3338 public: 3339 HSar(HValue* context, HValue* left, HValue* right) 3340 : HBitwiseBinaryOperation(context, left, right) { } 3341 3342 virtual Range* InferRange(Zone* zone); 3343 3344 static HInstruction* NewHSar(Zone* zone, 3345 HValue* context, 3346 HValue* left, 3347 HValue* right); 3348 3349 DECLARE_CONCRETE_INSTRUCTION(Sar) 3350 3351 protected: 3352 virtual bool DataEquals(HValue* other) { return true; } 3353 }; 3354 3355 3356 class HOsrEntry: public HTemplateInstruction<0> { 3357 public: 3358 explicit HOsrEntry(int ast_id) : ast_id_(ast_id) { 3359 SetGVNFlag(kChangesOsrEntries); 3360 } 3361 3362 int ast_id() const { return ast_id_; } 3363 3364 virtual Representation RequiredInputRepresentation(int index) { 3365 return Representation::None(); 3366 } 3367 3368 DECLARE_CONCRETE_INSTRUCTION(OsrEntry) 3369 3370 private: 3371 int ast_id_; 3372 }; 3373 3374 3375 class HParameter: public HTemplateInstruction<0> { 3376 public: 3377 explicit HParameter(unsigned index) : index_(index) { 3378 set_representation(Representation::Tagged()); 3379 } 3380 3381 unsigned index() const { return index_; } 3382 3383 virtual void PrintDataTo(StringStream* stream); 3384 3385 virtual Representation RequiredInputRepresentation(int index) { 3386 return Representation::None(); 3387 } 3388 3389 DECLARE_CONCRETE_INSTRUCTION(Parameter) 3390 3391 private: 3392 unsigned index_; 3393 }; 3394 3395 3396 class HCallStub: public HUnaryCall { 3397 public: 3398 HCallStub(HValue* context, CodeStub::Major major_key, int argument_count) 3399 : HUnaryCall(context, argument_count), 3400 major_key_(major_key), 3401 transcendental_type_(TranscendentalCache::kNumberOfCaches) { 3402 } 3403 3404 CodeStub::Major major_key() { return major_key_; } 3405 3406 HValue* context() { return value(); } 3407 3408 void set_transcendental_type(TranscendentalCache::Type transcendental_type) { 3409 transcendental_type_ = transcendental_type; 3410 } 3411 TranscendentalCache::Type transcendental_type() { 3412 return transcendental_type_; 3413 } 3414 3415 virtual void PrintDataTo(StringStream* stream); 3416 3417 virtual Representation RequiredInputRepresentation(int index) { 3418 return Representation::Tagged(); 3419 } 3420 3421 DECLARE_CONCRETE_INSTRUCTION(CallStub) 3422 3423 private: 3424 CodeStub::Major major_key_; 3425 TranscendentalCache::Type transcendental_type_; 3426 }; 3427 3428 3429 class HUnknownOSRValue: public HTemplateInstruction<0> { 3430 public: 3431 HUnknownOSRValue() 3432 : incoming_value_(NULL) { 3433 set_representation(Representation::Tagged()); 3434 } 3435 3436 virtual Representation RequiredInputRepresentation(int index) { 3437 return Representation::None(); 3438 } 3439 3440 void set_incoming_value(HPhi* value) { 3441 incoming_value_ = value; 3442 } 3443 3444 HPhi* incoming_value() { 3445 return incoming_value_; 3446 } 3447 3448 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue) 3449 3450 private: 3451 HPhi* incoming_value_; 3452 }; 3453 3454 3455 class HLoadGlobalCell: public HTemplateInstruction<0> { 3456 public: 3457 HLoadGlobalCell(Handle<JSGlobalPropertyCell> cell, PropertyDetails details) 3458 : cell_(cell), details_(details) { 3459 set_representation(Representation::Tagged()); 3460 SetFlag(kUseGVN); 3461 SetGVNFlag(kDependsOnGlobalVars); 3462 } 3463 3464 Handle<JSGlobalPropertyCell> cell() const { return cell_; } 3465 bool RequiresHoleCheck(); 3466 3467 virtual void PrintDataTo(StringStream* stream); 3468 3469 virtual intptr_t Hashcode() { 3470 ASSERT(!HEAP->allow_allocation(false)); 3471 return reinterpret_cast<intptr_t>(*cell_); 3472 } 3473 3474 virtual Representation RequiredInputRepresentation(int index) { 3475 return Representation::None(); 3476 } 3477 3478 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell) 3479 3480 protected: 3481 virtual bool DataEquals(HValue* other) { 3482 HLoadGlobalCell* b = HLoadGlobalCell::cast(other); 3483 return cell_.is_identical_to(b->cell()); 3484 } 3485 3486 private: 3487 Handle<JSGlobalPropertyCell> cell_; 3488 PropertyDetails details_; 3489 }; 3490 3491 3492 class HLoadGlobalGeneric: public HTemplateInstruction<2> { 3493 public: 3494 HLoadGlobalGeneric(HValue* context, 3495 HValue* global_object, 3496 Handle<Object> name, 3497 bool for_typeof) 3498 : name_(name), 3499 for_typeof_(for_typeof) { 3500 SetOperandAt(0, context); 3501 SetOperandAt(1, global_object); 3502 set_representation(Representation::Tagged()); 3503 SetAllSideEffects(); 3504 } 3505 3506 HValue* context() { return OperandAt(0); } 3507 HValue* global_object() { return OperandAt(1); } 3508 Handle<Object> name() const { return name_; } 3509 bool for_typeof() const { return for_typeof_; } 3510 3511 virtual void PrintDataTo(StringStream* stream); 3512 3513 virtual Representation RequiredInputRepresentation(int index) { 3514 return Representation::Tagged(); 3515 } 3516 3517 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric) 3518 3519 private: 3520 Handle<Object> name_; 3521 bool for_typeof_; 3522 }; 3523 3524 3525 inline bool StoringValueNeedsWriteBarrier(HValue* value) { 3526 return !value->type().IsBoolean() 3527 && !value->type().IsSmi() 3528 && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable()); 3529 } 3530 3531 3532 class HStoreGlobalCell: public HUnaryOperation { 3533 public: 3534 HStoreGlobalCell(HValue* value, 3535 Handle<JSGlobalPropertyCell> cell, 3536 PropertyDetails details) 3537 : HUnaryOperation(value), 3538 cell_(cell), 3539 details_(details) { 3540 SetGVNFlag(kChangesGlobalVars); 3541 } 3542 3543 Handle<JSGlobalPropertyCell> cell() const { return cell_; } 3544 bool RequiresHoleCheck() { 3545 return !details_.IsDontDelete() || details_.IsReadOnly(); 3546 } 3547 bool NeedsWriteBarrier() { 3548 return StoringValueNeedsWriteBarrier(value()); 3549 } 3550 3551 virtual Representation RequiredInputRepresentation(int index) { 3552 return Representation::Tagged(); 3553 } 3554 virtual void PrintDataTo(StringStream* stream); 3555 3556 DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell) 3557 3558 private: 3559 Handle<JSGlobalPropertyCell> cell_; 3560 PropertyDetails details_; 3561 }; 3562 3563 3564 class HStoreGlobalGeneric: public HTemplateInstruction<3> { 3565 public: 3566 HStoreGlobalGeneric(HValue* context, 3567 HValue* global_object, 3568 Handle<Object> name, 3569 HValue* value, 3570 StrictModeFlag strict_mode_flag) 3571 : name_(name), 3572 strict_mode_flag_(strict_mode_flag) { 3573 SetOperandAt(0, context); 3574 SetOperandAt(1, global_object); 3575 SetOperandAt(2, value); 3576 set_representation(Representation::Tagged()); 3577 SetAllSideEffects(); 3578 } 3579 3580 HValue* context() { return OperandAt(0); } 3581 HValue* global_object() { return OperandAt(1); } 3582 Handle<Object> name() const { return name_; } 3583 HValue* value() { return OperandAt(2); } 3584 StrictModeFlag strict_mode_flag() { return strict_mode_flag_; } 3585 3586 virtual void PrintDataTo(StringStream* stream); 3587 3588 virtual Representation RequiredInputRepresentation(int index) { 3589 return Representation::Tagged(); 3590 } 3591 3592 DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric) 3593 3594 private: 3595 Handle<Object> name_; 3596 StrictModeFlag strict_mode_flag_; 3597 }; 3598 3599 3600 class HLoadContextSlot: public HUnaryOperation { 3601 public: 3602 enum Mode { 3603 // Perform a normal load of the context slot without checking its value. 3604 kNoCheck, 3605 // Load and check the value of the context slot. Deoptimize if it's the 3606 // hole value. This is used for checking for loading of uninitialized 3607 // harmony bindings where we deoptimize into full-codegen generated code 3608 // which will subsequently throw a reference error. 3609 kCheckDeoptimize, 3610 // Load and check the value of the context slot. Return undefined if it's 3611 // the hole value. This is used for non-harmony const assignments 3612 kCheckReturnUndefined 3613 }; 3614 3615 HLoadContextSlot(HValue* context, Variable* var) 3616 : HUnaryOperation(context), slot_index_(var->index()) { 3617 ASSERT(var->IsContextSlot()); 3618 switch (var->mode()) { 3619 case LET: 3620 case CONST_HARMONY: 3621 mode_ = kCheckDeoptimize; 3622 break; 3623 case CONST: 3624 mode_ = kCheckReturnUndefined; 3625 break; 3626 default: 3627 mode_ = kNoCheck; 3628 } 3629 set_representation(Representation::Tagged()); 3630 SetFlag(kUseGVN); 3631 SetGVNFlag(kDependsOnContextSlots); 3632 } 3633 3634 int slot_index() const { return slot_index_; } 3635 Mode mode() const { return mode_; } 3636 3637 bool DeoptimizesOnHole() { 3638 return mode_ == kCheckDeoptimize; 3639 } 3640 3641 bool RequiresHoleCheck() { 3642 return mode_ != kNoCheck; 3643 } 3644 3645 virtual Representation RequiredInputRepresentation(int index) { 3646 return Representation::Tagged(); 3647 } 3648 3649 virtual void PrintDataTo(StringStream* stream); 3650 3651 DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot) 3652 3653 protected: 3654 virtual bool DataEquals(HValue* other) { 3655 HLoadContextSlot* b = HLoadContextSlot::cast(other); 3656 return (slot_index() == b->slot_index()); 3657 } 3658 3659 private: 3660 int slot_index_; 3661 Mode mode_; 3662 }; 3663 3664 3665 class HStoreContextSlot: public HTemplateInstruction<2> { 3666 public: 3667 enum Mode { 3668 // Perform a normal store to the context slot without checking its previous 3669 // value. 3670 kNoCheck, 3671 // Check the previous value of the context slot and deoptimize if it's the 3672 // hole value. This is used for checking for assignments to uninitialized 3673 // harmony bindings where we deoptimize into full-codegen generated code 3674 // which will subsequently throw a reference error. 3675 kCheckDeoptimize, 3676 // Check the previous value and ignore assignment if it isn't a hole value 3677 kCheckIgnoreAssignment 3678 }; 3679 3680 HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value) 3681 : slot_index_(slot_index), mode_(mode) { 3682 SetOperandAt(0, context); 3683 SetOperandAt(1, value); 3684 SetGVNFlag(kChangesContextSlots); 3685 } 3686 3687 HValue* context() { return OperandAt(0); } 3688 HValue* value() { return OperandAt(1); } 3689 int slot_index() const { return slot_index_; } 3690 Mode mode() const { return mode_; } 3691 3692 bool NeedsWriteBarrier() { 3693 return StoringValueNeedsWriteBarrier(value()); 3694 } 3695 3696 bool DeoptimizesOnHole() { 3697 return mode_ == kCheckDeoptimize; 3698 } 3699 3700 bool RequiresHoleCheck() { 3701 return mode_ != kNoCheck; 3702 } 3703 3704 virtual Representation RequiredInputRepresentation(int index) { 3705 return Representation::Tagged(); 3706 } 3707 3708 virtual void PrintDataTo(StringStream* stream); 3709 3710 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot) 3711 3712 private: 3713 int slot_index_; 3714 Mode mode_; 3715 }; 3716 3717 3718 class HLoadNamedField: public HUnaryOperation { 3719 public: 3720 HLoadNamedField(HValue* object, bool is_in_object, int offset) 3721 : HUnaryOperation(object), 3722 is_in_object_(is_in_object), 3723 offset_(offset) { 3724 set_representation(Representation::Tagged()); 3725 SetFlag(kUseGVN); 3726 SetGVNFlag(kDependsOnMaps); 3727 if (is_in_object) { 3728 SetGVNFlag(kDependsOnInobjectFields); 3729 } else { 3730 SetGVNFlag(kDependsOnBackingStoreFields); 3731 } 3732 } 3733 3734 HValue* object() { return OperandAt(0); } 3735 bool is_in_object() const { return is_in_object_; } 3736 int offset() const { return offset_; } 3737 3738 virtual Representation RequiredInputRepresentation(int index) { 3739 return Representation::Tagged(); 3740 } 3741 virtual void PrintDataTo(StringStream* stream); 3742 3743 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField) 3744 3745 protected: 3746 virtual bool DataEquals(HValue* other) { 3747 HLoadNamedField* b = HLoadNamedField::cast(other); 3748 return is_in_object_ == b->is_in_object_ && offset_ == b->offset_; 3749 } 3750 3751 private: 3752 bool is_in_object_; 3753 int offset_; 3754 }; 3755 3756 3757 class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> { 3758 public: 3759 HLoadNamedFieldPolymorphic(HValue* context, 3760 HValue* object, 3761 SmallMapList* types, 3762 Handle<String> name); 3763 3764 HValue* context() { return OperandAt(0); } 3765 HValue* object() { return OperandAt(1); } 3766 SmallMapList* types() { return &types_; } 3767 Handle<String> name() { return name_; } 3768 bool need_generic() { return need_generic_; } 3769 3770 virtual Representation RequiredInputRepresentation(int index) { 3771 return Representation::Tagged(); 3772 } 3773 3774 virtual void PrintDataTo(StringStream* stream); 3775 3776 DECLARE_CONCRETE_INSTRUCTION(LoadNamedFieldPolymorphic) 3777 3778 static const int kMaxLoadPolymorphism = 4; 3779 3780 protected: 3781 virtual bool DataEquals(HValue* value); 3782 3783 private: 3784 SmallMapList types_; 3785 Handle<String> name_; 3786 bool need_generic_; 3787 }; 3788 3789 3790 3791 class HLoadNamedGeneric: public HTemplateInstruction<2> { 3792 public: 3793 HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name) 3794 : name_(name) { 3795 SetOperandAt(0, context); 3796 SetOperandAt(1, object); 3797 set_representation(Representation::Tagged()); 3798 SetAllSideEffects(); 3799 } 3800 3801 HValue* context() { return OperandAt(0); } 3802 HValue* object() { return OperandAt(1); } 3803 Handle<Object> name() const { return name_; } 3804 3805 virtual Representation RequiredInputRepresentation(int index) { 3806 return Representation::Tagged(); 3807 } 3808 3809 virtual void PrintDataTo(StringStream* stream); 3810 3811 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric) 3812 3813 private: 3814 Handle<Object> name_; 3815 }; 3816 3817 3818 class HLoadFunctionPrototype: public HUnaryOperation { 3819 public: 3820 explicit HLoadFunctionPrototype(HValue* function) 3821 : HUnaryOperation(function) { 3822 set_representation(Representation::Tagged()); 3823 SetFlag(kUseGVN); 3824 SetGVNFlag(kDependsOnCalls); 3825 } 3826 3827 HValue* function() { return OperandAt(0); } 3828 3829 virtual Representation RequiredInputRepresentation(int index) { 3830 return Representation::Tagged(); 3831 } 3832 3833 DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype) 3834 3835 protected: 3836 virtual bool DataEquals(HValue* other) { return true; } 3837 }; 3838 3839 3840 class HLoadKeyedFastElement: public HTemplateInstruction<2> { 3841 public: 3842 enum HoleCheckMode { PERFORM_HOLE_CHECK, OMIT_HOLE_CHECK }; 3843 3844 HLoadKeyedFastElement(HValue* obj, 3845 HValue* key, 3846 HoleCheckMode hole_check_mode = PERFORM_HOLE_CHECK) 3847 : hole_check_mode_(hole_check_mode) { 3848 SetOperandAt(0, obj); 3849 SetOperandAt(1, key); 3850 set_representation(Representation::Tagged()); 3851 SetGVNFlag(kDependsOnArrayElements); 3852 SetFlag(kUseGVN); 3853 } 3854 3855 HValue* object() { return OperandAt(0); } 3856 HValue* key() { return OperandAt(1); } 3857 3858 virtual Representation RequiredInputRepresentation(int index) { 3859 // The key is supposed to be Integer32. 3860 return index == 0 3861 ? Representation::Tagged() 3862 : Representation::Integer32(); 3863 } 3864 3865 virtual void PrintDataTo(StringStream* stream); 3866 3867 bool RequiresHoleCheck(); 3868 3869 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement) 3870 3871 protected: 3872 virtual bool DataEquals(HValue* other) { 3873 if (!other->IsLoadKeyedFastElement()) return false; 3874 HLoadKeyedFastElement* other_load = HLoadKeyedFastElement::cast(other); 3875 return hole_check_mode_ == other_load->hole_check_mode_; 3876 } 3877 3878 private: 3879 HoleCheckMode hole_check_mode_; 3880 }; 3881 3882 3883 class HLoadKeyedFastDoubleElement: public HTemplateInstruction<2> { 3884 public: 3885 HLoadKeyedFastDoubleElement(HValue* elements, HValue* key) { 3886 SetOperandAt(0, elements); 3887 SetOperandAt(1, key); 3888 set_representation(Representation::Double()); 3889 SetGVNFlag(kDependsOnDoubleArrayElements); 3890 SetFlag(kUseGVN); 3891 } 3892 3893 HValue* elements() { return OperandAt(0); } 3894 HValue* key() { return OperandAt(1); } 3895 3896 virtual Representation RequiredInputRepresentation(int index) { 3897 // The key is supposed to be Integer32. 3898 return index == 0 3899 ? Representation::Tagged() 3900 : Representation::Integer32(); 3901 } 3902 3903 virtual void PrintDataTo(StringStream* stream); 3904 3905 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement) 3906 3907 protected: 3908 virtual bool DataEquals(HValue* other) { return true; } 3909 }; 3910 3911 3912 class HLoadKeyedSpecializedArrayElement: public HTemplateInstruction<2> { 3913 public: 3914 HLoadKeyedSpecializedArrayElement(HValue* external_elements, 3915 HValue* key, 3916 ElementsKind elements_kind) 3917 : elements_kind_(elements_kind) { 3918 SetOperandAt(0, external_elements); 3919 SetOperandAt(1, key); 3920 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || 3921 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 3922 set_representation(Representation::Double()); 3923 } else { 3924 set_representation(Representation::Integer32()); 3925 } 3926 SetGVNFlag(kDependsOnSpecializedArrayElements); 3927 // Native code could change the specialized array. 3928 SetGVNFlag(kDependsOnCalls); 3929 SetFlag(kUseGVN); 3930 } 3931 3932 virtual void PrintDataTo(StringStream* stream); 3933 3934 virtual Representation RequiredInputRepresentation(int index) { 3935 // The key is supposed to be Integer32, but the base pointer 3936 // for the element load is a naked pointer. 3937 return index == 0 3938 ? Representation::External() 3939 : Representation::Integer32(); 3940 } 3941 3942 HValue* external_pointer() { return OperandAt(0); } 3943 HValue* key() { return OperandAt(1); } 3944 ElementsKind elements_kind() const { return elements_kind_; } 3945 3946 virtual Range* InferRange(Zone* zone); 3947 3948 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement) 3949 3950 protected: 3951 virtual bool DataEquals(HValue* other) { 3952 if (!other->IsLoadKeyedSpecializedArrayElement()) return false; 3953 HLoadKeyedSpecializedArrayElement* cast_other = 3954 HLoadKeyedSpecializedArrayElement::cast(other); 3955 return elements_kind_ == cast_other->elements_kind(); 3956 } 3957 3958 private: 3959 ElementsKind elements_kind_; 3960 }; 3961 3962 3963 class HLoadKeyedGeneric: public HTemplateInstruction<3> { 3964 public: 3965 HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key) { 3966 set_representation(Representation::Tagged()); 3967 SetOperandAt(0, obj); 3968 SetOperandAt(1, key); 3969 SetOperandAt(2, context); 3970 SetAllSideEffects(); 3971 } 3972 3973 HValue* object() { return OperandAt(0); } 3974 HValue* key() { return OperandAt(1); } 3975 HValue* context() { return OperandAt(2); } 3976 3977 virtual void PrintDataTo(StringStream* stream); 3978 3979 virtual Representation RequiredInputRepresentation(int index) { 3980 return Representation::Tagged(); 3981 } 3982 3983 virtual HValue* Canonicalize(); 3984 3985 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric) 3986 }; 3987 3988 3989 class HStoreNamedField: public HTemplateInstruction<2> { 3990 public: 3991 HStoreNamedField(HValue* obj, 3992 Handle<String> name, 3993 HValue* val, 3994 bool in_object, 3995 int offset) 3996 : name_(name), 3997 is_in_object_(in_object), 3998 offset_(offset) { 3999 SetOperandAt(0, obj); 4000 SetOperandAt(1, val); 4001 if (is_in_object_) { 4002 SetGVNFlag(kChangesInobjectFields); 4003 } else { 4004 SetGVNFlag(kChangesBackingStoreFields); 4005 } 4006 } 4007 4008 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField) 4009 4010 virtual Representation RequiredInputRepresentation(int index) { 4011 return Representation::Tagged(); 4012 } 4013 virtual void PrintDataTo(StringStream* stream); 4014 4015 HValue* object() { return OperandAt(0); } 4016 HValue* value() { return OperandAt(1); } 4017 4018 Handle<String> name() const { return name_; } 4019 bool is_in_object() const { return is_in_object_; } 4020 int offset() const { return offset_; } 4021 Handle<Map> transition() const { return transition_; } 4022 void set_transition(Handle<Map> map) { transition_ = map; } 4023 4024 bool NeedsWriteBarrier() { 4025 return StoringValueNeedsWriteBarrier(value()); 4026 } 4027 4028 private: 4029 Handle<String> name_; 4030 bool is_in_object_; 4031 int offset_; 4032 Handle<Map> transition_; 4033 }; 4034 4035 4036 class HStoreNamedGeneric: public HTemplateInstruction<3> { 4037 public: 4038 HStoreNamedGeneric(HValue* context, 4039 HValue* object, 4040 Handle<String> name, 4041 HValue* value, 4042 StrictModeFlag strict_mode_flag) 4043 : name_(name), 4044 strict_mode_flag_(strict_mode_flag) { 4045 SetOperandAt(0, object); 4046 SetOperandAt(1, value); 4047 SetOperandAt(2, context); 4048 SetAllSideEffects(); 4049 } 4050 4051 HValue* object() { return OperandAt(0); } 4052 HValue* value() { return OperandAt(1); } 4053 HValue* context() { return OperandAt(2); } 4054 Handle<String> name() { return name_; } 4055 StrictModeFlag strict_mode_flag() { return strict_mode_flag_; } 4056 4057 virtual void PrintDataTo(StringStream* stream); 4058 4059 virtual Representation RequiredInputRepresentation(int index) { 4060 return Representation::Tagged(); 4061 } 4062 4063 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric) 4064 4065 private: 4066 Handle<String> name_; 4067 StrictModeFlag strict_mode_flag_; 4068 }; 4069 4070 4071 class HStoreKeyedFastElement: public HTemplateInstruction<3> { 4072 public: 4073 HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val, 4074 ElementsKind elements_kind = FAST_ELEMENTS) 4075 : elements_kind_(elements_kind) { 4076 SetOperandAt(0, obj); 4077 SetOperandAt(1, key); 4078 SetOperandAt(2, val); 4079 SetGVNFlag(kChangesArrayElements); 4080 } 4081 4082 virtual Representation RequiredInputRepresentation(int index) { 4083 // The key is supposed to be Integer32. 4084 return index == 1 4085 ? Representation::Integer32() 4086 : Representation::Tagged(); 4087 } 4088 4089 HValue* object() { return OperandAt(0); } 4090 HValue* key() { return OperandAt(1); } 4091 HValue* value() { return OperandAt(2); } 4092 bool value_is_smi() { 4093 return elements_kind_ == FAST_SMI_ONLY_ELEMENTS; 4094 } 4095 4096 bool NeedsWriteBarrier() { 4097 if (value_is_smi()) { 4098 return false; 4099 } else { 4100 return StoringValueNeedsWriteBarrier(value()); 4101 } 4102 } 4103 4104 virtual void PrintDataTo(StringStream* stream); 4105 4106 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement) 4107 4108 private: 4109 ElementsKind elements_kind_; 4110 }; 4111 4112 4113 class HStoreKeyedFastDoubleElement: public HTemplateInstruction<3> { 4114 public: 4115 HStoreKeyedFastDoubleElement(HValue* elements, 4116 HValue* key, 4117 HValue* val) { 4118 SetOperandAt(0, elements); 4119 SetOperandAt(1, key); 4120 SetOperandAt(2, val); 4121 SetGVNFlag(kChangesDoubleArrayElements); 4122 } 4123 4124 virtual Representation RequiredInputRepresentation(int index) { 4125 if (index == 1) { 4126 return Representation::Integer32(); 4127 } else if (index == 2) { 4128 return Representation::Double(); 4129 } else { 4130 return Representation::Tagged(); 4131 } 4132 } 4133 4134 HValue* elements() { return OperandAt(0); } 4135 HValue* key() { return OperandAt(1); } 4136 HValue* value() { return OperandAt(2); } 4137 4138 bool NeedsWriteBarrier() { 4139 return StoringValueNeedsWriteBarrier(value()); 4140 } 4141 4142 virtual void PrintDataTo(StringStream* stream); 4143 4144 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement) 4145 }; 4146 4147 4148 class HStoreKeyedSpecializedArrayElement: public HTemplateInstruction<3> { 4149 public: 4150 HStoreKeyedSpecializedArrayElement(HValue* external_elements, 4151 HValue* key, 4152 HValue* val, 4153 ElementsKind elements_kind) 4154 : elements_kind_(elements_kind) { 4155 SetGVNFlag(kChangesSpecializedArrayElements); 4156 SetOperandAt(0, external_elements); 4157 SetOperandAt(1, key); 4158 SetOperandAt(2, val); 4159 } 4160 4161 virtual void PrintDataTo(StringStream* stream); 4162 4163 virtual Representation RequiredInputRepresentation(int index) { 4164 if (index == 0) { 4165 return Representation::External(); 4166 } else { 4167 bool float_or_double_elements = 4168 elements_kind() == EXTERNAL_FLOAT_ELEMENTS || 4169 elements_kind() == EXTERNAL_DOUBLE_ELEMENTS; 4170 if (index == 2 && float_or_double_elements) { 4171 return Representation::Double(); 4172 } else { 4173 return Representation::Integer32(); 4174 } 4175 } 4176 } 4177 4178 HValue* external_pointer() { return OperandAt(0); } 4179 HValue* key() { return OperandAt(1); } 4180 HValue* value() { return OperandAt(2); } 4181 ElementsKind elements_kind() const { return elements_kind_; } 4182 4183 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedSpecializedArrayElement) 4184 4185 private: 4186 ElementsKind elements_kind_; 4187 }; 4188 4189 4190 class HStoreKeyedGeneric: public HTemplateInstruction<4> { 4191 public: 4192 HStoreKeyedGeneric(HValue* context, 4193 HValue* object, 4194 HValue* key, 4195 HValue* value, 4196 StrictModeFlag strict_mode_flag) 4197 : strict_mode_flag_(strict_mode_flag) { 4198 SetOperandAt(0, object); 4199 SetOperandAt(1, key); 4200 SetOperandAt(2, value); 4201 SetOperandAt(3, context); 4202 SetAllSideEffects(); 4203 } 4204 4205 HValue* object() { return OperandAt(0); } 4206 HValue* key() { return OperandAt(1); } 4207 HValue* value() { return OperandAt(2); } 4208 HValue* context() { return OperandAt(3); } 4209 StrictModeFlag strict_mode_flag() { return strict_mode_flag_; } 4210 4211 virtual Representation RequiredInputRepresentation(int index) { 4212 return Representation::Tagged(); 4213 } 4214 4215 virtual void PrintDataTo(StringStream* stream); 4216 4217 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric) 4218 4219 private: 4220 StrictModeFlag strict_mode_flag_; 4221 }; 4222 4223 4224 class HTransitionElementsKind: public HTemplateInstruction<1> { 4225 public: 4226 HTransitionElementsKind(HValue* object, 4227 Handle<Map> original_map, 4228 Handle<Map> transitioned_map) 4229 : original_map_(original_map), 4230 transitioned_map_(transitioned_map) { 4231 SetOperandAt(0, object); 4232 SetFlag(kUseGVN); 4233 SetGVNFlag(kChangesElementsKind); 4234 SetGVNFlag(kChangesElementsPointer); 4235 set_representation(Representation::Tagged()); 4236 } 4237 4238 virtual Representation RequiredInputRepresentation(int index) { 4239 return Representation::Tagged(); 4240 } 4241 4242 HValue* object() { return OperandAt(0); } 4243 Handle<Map> original_map() { return original_map_; } 4244 Handle<Map> transitioned_map() { return transitioned_map_; } 4245 4246 virtual void PrintDataTo(StringStream* stream); 4247 4248 DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind) 4249 4250 protected: 4251 virtual bool DataEquals(HValue* other) { 4252 HTransitionElementsKind* instr = HTransitionElementsKind::cast(other); 4253 return original_map_.is_identical_to(instr->original_map()) && 4254 transitioned_map_.is_identical_to(instr->transitioned_map()); 4255 } 4256 4257 private: 4258 Handle<Map> original_map_; 4259 Handle<Map> transitioned_map_; 4260 }; 4261 4262 4263 class HStringAdd: public HBinaryOperation { 4264 public: 4265 HStringAdd(HValue* context, HValue* left, HValue* right) 4266 : HBinaryOperation(context, left, right) { 4267 set_representation(Representation::Tagged()); 4268 SetFlag(kUseGVN); 4269 SetGVNFlag(kDependsOnMaps); 4270 } 4271 4272 virtual Representation RequiredInputRepresentation(int index) { 4273 return Representation::Tagged(); 4274 } 4275 4276 virtual HType CalculateInferredType() { 4277 return HType::String(); 4278 } 4279 4280 DECLARE_CONCRETE_INSTRUCTION(StringAdd) 4281 4282 protected: 4283 virtual bool DataEquals(HValue* other) { return true; } 4284 }; 4285 4286 4287 class HStringCharCodeAt: public HTemplateInstruction<3> { 4288 public: 4289 HStringCharCodeAt(HValue* context, HValue* string, HValue* index) { 4290 SetOperandAt(0, context); 4291 SetOperandAt(1, string); 4292 SetOperandAt(2, index); 4293 set_representation(Representation::Integer32()); 4294 SetFlag(kUseGVN); 4295 SetGVNFlag(kDependsOnMaps); 4296 } 4297 4298 virtual Representation RequiredInputRepresentation(int index) { 4299 // The index is supposed to be Integer32. 4300 return index == 2 4301 ? Representation::Integer32() 4302 : Representation::Tagged(); 4303 } 4304 4305 HValue* context() { return OperandAt(0); } 4306 HValue* string() { return OperandAt(1); } 4307 HValue* index() { return OperandAt(2); } 4308 4309 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt) 4310 4311 protected: 4312 virtual bool DataEquals(HValue* other) { return true; } 4313 4314 virtual Range* InferRange(Zone* zone) { 4315 return new(zone) Range(0, String::kMaxUtf16CodeUnit); 4316 } 4317 }; 4318 4319 4320 class HStringCharFromCode: public HTemplateInstruction<2> { 4321 public: 4322 HStringCharFromCode(HValue* context, HValue* char_code) { 4323 SetOperandAt(0, context); 4324 SetOperandAt(1, char_code); 4325 set_representation(Representation::Tagged()); 4326 SetFlag(kUseGVN); 4327 } 4328 4329 virtual Representation RequiredInputRepresentation(int index) { 4330 return index == 0 4331 ? Representation::Tagged() 4332 : Representation::Integer32(); 4333 } 4334 virtual HType CalculateInferredType(); 4335 4336 HValue* context() { return OperandAt(0); } 4337 HValue* value() { return OperandAt(1); } 4338 4339 virtual bool DataEquals(HValue* other) { return true; } 4340 4341 DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode) 4342 }; 4343 4344 4345 class HStringLength: public HUnaryOperation { 4346 public: 4347 explicit HStringLength(HValue* string) : HUnaryOperation(string) { 4348 set_representation(Representation::Tagged()); 4349 SetFlag(kUseGVN); 4350 SetGVNFlag(kDependsOnMaps); 4351 } 4352 4353 virtual Representation RequiredInputRepresentation(int index) { 4354 return Representation::Tagged(); 4355 } 4356 4357 virtual HType CalculateInferredType() { 4358 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); 4359 return HType::Smi(); 4360 } 4361 4362 DECLARE_CONCRETE_INSTRUCTION(StringLength) 4363 4364 protected: 4365 virtual bool DataEquals(HValue* other) { return true; } 4366 4367 virtual Range* InferRange(Zone* zone) { 4368 return new(zone) Range(0, String::kMaxLength); 4369 } 4370 }; 4371 4372 4373 class HAllocateObject: public HTemplateInstruction<1> { 4374 public: 4375 HAllocateObject(HValue* context, Handle<JSFunction> constructor) 4376 : constructor_(constructor) { 4377 SetOperandAt(0, context); 4378 set_representation(Representation::Tagged()); 4379 } 4380 4381 HValue* context() { return OperandAt(0); } 4382 Handle<JSFunction> constructor() { return constructor_; } 4383 4384 virtual Representation RequiredInputRepresentation(int index) { 4385 return Representation::Tagged(); 4386 } 4387 virtual HType CalculateInferredType(); 4388 4389 DECLARE_CONCRETE_INSTRUCTION(AllocateObject) 4390 4391 private: 4392 Handle<JSFunction> constructor_; 4393 }; 4394 4395 4396 template <int V> 4397 class HMaterializedLiteral: public HTemplateInstruction<V> { 4398 public: 4399 HMaterializedLiteral<V>(int index, int depth) 4400 : literal_index_(index), depth_(depth) { 4401 this->set_representation(Representation::Tagged()); 4402 } 4403 4404 int literal_index() const { return literal_index_; } 4405 int depth() const { return depth_; } 4406 4407 private: 4408 int literal_index_; 4409 int depth_; 4410 }; 4411 4412 4413 class HFastLiteral: public HMaterializedLiteral<1> { 4414 public: 4415 HFastLiteral(HValue* context, 4416 Handle<JSObject> boilerplate, 4417 int total_size, 4418 int literal_index, 4419 int depth) 4420 : HMaterializedLiteral<1>(literal_index, depth), 4421 boilerplate_(boilerplate), 4422 total_size_(total_size) { 4423 SetOperandAt(0, context); 4424 } 4425 4426 // Maximum depth and total number of elements and properties for literal 4427 // graphs to be considered for fast deep-copying. 4428 static const int kMaxLiteralDepth = 3; 4429 static const int kMaxLiteralProperties = 8; 4430 4431 HValue* context() { return OperandAt(0); } 4432 Handle<JSObject> boilerplate() const { return boilerplate_; } 4433 int total_size() const { return total_size_; } 4434 4435 virtual Representation RequiredInputRepresentation(int index) { 4436 return Representation::Tagged(); 4437 } 4438 virtual HType CalculateInferredType(); 4439 4440 DECLARE_CONCRETE_INSTRUCTION(FastLiteral) 4441 4442 private: 4443 Handle<JSObject> boilerplate_; 4444 int total_size_; 4445 }; 4446 4447 4448 class HArrayLiteral: public HMaterializedLiteral<1> { 4449 public: 4450 HArrayLiteral(HValue* context, 4451 Handle<HeapObject> boilerplate_object, 4452 int length, 4453 int literal_index, 4454 int depth) 4455 : HMaterializedLiteral<1>(literal_index, depth), 4456 length_(length), 4457 boilerplate_object_(boilerplate_object) { 4458 SetOperandAt(0, context); 4459 } 4460 4461 HValue* context() { return OperandAt(0); } 4462 ElementsKind boilerplate_elements_kind() const { 4463 if (!boilerplate_object_->IsJSObject()) { 4464 return FAST_ELEMENTS; 4465 } 4466 return Handle<JSObject>::cast(boilerplate_object_)->GetElementsKind(); 4467 } 4468 Handle<HeapObject> boilerplate_object() const { return boilerplate_object_; } 4469 int length() const { return length_; } 4470 4471 bool IsCopyOnWrite() const; 4472 4473 virtual Representation RequiredInputRepresentation(int index) { 4474 return Representation::Tagged(); 4475 } 4476 virtual HType CalculateInferredType(); 4477 4478 DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral) 4479 4480 private: 4481 int length_; 4482 Handle<HeapObject> boilerplate_object_; 4483 }; 4484 4485 4486 class HObjectLiteral: public HMaterializedLiteral<1> { 4487 public: 4488 HObjectLiteral(HValue* context, 4489 Handle<FixedArray> constant_properties, 4490 bool fast_elements, 4491 int literal_index, 4492 int depth, 4493 bool has_function) 4494 : HMaterializedLiteral<1>(literal_index, depth), 4495 constant_properties_(constant_properties), 4496 fast_elements_(fast_elements), 4497 has_function_(has_function) { 4498 SetOperandAt(0, context); 4499 } 4500 4501 HValue* context() { return OperandAt(0); } 4502 Handle<FixedArray> constant_properties() const { 4503 return constant_properties_; 4504 } 4505 bool fast_elements() const { return fast_elements_; } 4506 bool has_function() const { return has_function_; } 4507 4508 virtual Representation RequiredInputRepresentation(int index) { 4509 return Representation::Tagged(); 4510 } 4511 virtual HType CalculateInferredType(); 4512 4513 DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral) 4514 4515 private: 4516 Handle<FixedArray> constant_properties_; 4517 bool fast_elements_; 4518 bool has_function_; 4519 }; 4520 4521 4522 class HRegExpLiteral: public HMaterializedLiteral<1> { 4523 public: 4524 HRegExpLiteral(HValue* context, 4525 Handle<String> pattern, 4526 Handle<String> flags, 4527 int literal_index) 4528 : HMaterializedLiteral<1>(literal_index, 0), 4529 pattern_(pattern), 4530 flags_(flags) { 4531 SetOperandAt(0, context); 4532 SetAllSideEffects(); 4533 } 4534 4535 HValue* context() { return OperandAt(0); } 4536 Handle<String> pattern() { return pattern_; } 4537 Handle<String> flags() { return flags_; } 4538 4539 virtual Representation RequiredInputRepresentation(int index) { 4540 return Representation::Tagged(); 4541 } 4542 virtual HType CalculateInferredType(); 4543 4544 DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral) 4545 4546 private: 4547 Handle<String> pattern_; 4548 Handle<String> flags_; 4549 }; 4550 4551 4552 class HFunctionLiteral: public HTemplateInstruction<1> { 4553 public: 4554 HFunctionLiteral(HValue* context, 4555 Handle<SharedFunctionInfo> shared, 4556 bool pretenure) 4557 : shared_info_(shared), pretenure_(pretenure) { 4558 SetOperandAt(0, context); 4559 set_representation(Representation::Tagged()); 4560 } 4561 4562 HValue* context() { return OperandAt(0); } 4563 4564 virtual Representation RequiredInputRepresentation(int index) { 4565 return Representation::Tagged(); 4566 } 4567 virtual HType CalculateInferredType(); 4568 4569 DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral) 4570 4571 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; } 4572 bool pretenure() const { return pretenure_; } 4573 4574 private: 4575 Handle<SharedFunctionInfo> shared_info_; 4576 bool pretenure_; 4577 }; 4578 4579 4580 class HTypeof: public HTemplateInstruction<2> { 4581 public: 4582 explicit HTypeof(HValue* context, HValue* value) { 4583 SetOperandAt(0, context); 4584 SetOperandAt(1, value); 4585 set_representation(Representation::Tagged()); 4586 } 4587 4588 HValue* context() { return OperandAt(0); } 4589 HValue* value() { return OperandAt(1); } 4590 4591 virtual HValue* Canonicalize(); 4592 virtual void PrintDataTo(StringStream* stream); 4593 4594 virtual Representation RequiredInputRepresentation(int index) { 4595 return Representation::Tagged(); 4596 } 4597 4598 DECLARE_CONCRETE_INSTRUCTION(Typeof) 4599 }; 4600 4601 4602 class HToFastProperties: public HUnaryOperation { 4603 public: 4604 explicit HToFastProperties(HValue* value) : HUnaryOperation(value) { 4605 // This instruction is not marked as having side effects, but 4606 // changes the map of the input operand. Use it only when creating 4607 // object literals. 4608 ASSERT(value->IsObjectLiteral() || value->IsFastLiteral()); 4609 set_representation(Representation::Tagged()); 4610 } 4611 4612 virtual Representation RequiredInputRepresentation(int index) { 4613 return Representation::Tagged(); 4614 } 4615 4616 DECLARE_CONCRETE_INSTRUCTION(ToFastProperties) 4617 }; 4618 4619 4620 class HValueOf: public HUnaryOperation { 4621 public: 4622 explicit HValueOf(HValue* value) : HUnaryOperation(value) { 4623 set_representation(Representation::Tagged()); 4624 } 4625 4626 virtual Representation RequiredInputRepresentation(int index) { 4627 return Representation::Tagged(); 4628 } 4629 4630 DECLARE_CONCRETE_INSTRUCTION(ValueOf) 4631 }; 4632 4633 4634 class HDateField: public HUnaryOperation { 4635 public: 4636 HDateField(HValue* date, Smi* index) 4637 : HUnaryOperation(date), index_(index) { 4638 set_representation(Representation::Tagged()); 4639 } 4640 4641 Smi* index() const { return index_; } 4642 4643 virtual Representation RequiredInputRepresentation(int index) { 4644 return Representation::Tagged(); 4645 } 4646 4647 DECLARE_CONCRETE_INSTRUCTION(DateField) 4648 4649 private: 4650 Smi* index_; 4651 }; 4652 4653 4654 class HDeleteProperty: public HBinaryOperation { 4655 public: 4656 HDeleteProperty(HValue* context, HValue* obj, HValue* key) 4657 : HBinaryOperation(context, obj, key) { 4658 set_representation(Representation::Tagged()); 4659 SetAllSideEffects(); 4660 } 4661 4662 virtual Representation RequiredInputRepresentation(int index) { 4663 return Representation::Tagged(); 4664 } 4665 4666 virtual HType CalculateInferredType(); 4667 4668 DECLARE_CONCRETE_INSTRUCTION(DeleteProperty) 4669 4670 HValue* object() { return left(); } 4671 HValue* key() { return right(); } 4672 }; 4673 4674 4675 class HIn: public HTemplateInstruction<3> { 4676 public: 4677 HIn(HValue* context, HValue* key, HValue* object) { 4678 SetOperandAt(0, context); 4679 SetOperandAt(1, key); 4680 SetOperandAt(2, object); 4681 set_representation(Representation::Tagged()); 4682 SetAllSideEffects(); 4683 } 4684 4685 HValue* context() { return OperandAt(0); } 4686 HValue* key() { return OperandAt(1); } 4687 HValue* object() { return OperandAt(2); } 4688 4689 virtual Representation RequiredInputRepresentation(int index) { 4690 return Representation::Tagged(); 4691 } 4692 4693 virtual HType CalculateInferredType() { 4694 return HType::Boolean(); 4695 } 4696 4697 virtual void PrintDataTo(StringStream* stream); 4698 4699 DECLARE_CONCRETE_INSTRUCTION(In) 4700 }; 4701 4702 4703 class HCheckMapValue: public HTemplateInstruction<2> { 4704 public: 4705 HCheckMapValue(HValue* value, 4706 HValue* map) { 4707 SetOperandAt(0, value); 4708 SetOperandAt(1, map); 4709 set_representation(Representation::Tagged()); 4710 SetFlag(kUseGVN); 4711 SetGVNFlag(kDependsOnMaps); 4712 SetGVNFlag(kDependsOnElementsKind); 4713 } 4714 4715 virtual Representation RequiredInputRepresentation(int index) { 4716 return Representation::Tagged(); 4717 } 4718 4719 virtual void PrintDataTo(StringStream* stream); 4720 4721 virtual HType CalculateInferredType() { 4722 return HType::Tagged(); 4723 } 4724 4725 HValue* value() { return OperandAt(0); } 4726 HValue* map() { return OperandAt(1); } 4727 4728 DECLARE_CONCRETE_INSTRUCTION(CheckMapValue) 4729 4730 protected: 4731 virtual bool DataEquals(HValue* other) { 4732 return true; 4733 } 4734 }; 4735 4736 4737 class HForInPrepareMap : public HTemplateInstruction<2> { 4738 public: 4739 HForInPrepareMap(HValue* context, 4740 HValue* object) { 4741 SetOperandAt(0, context); 4742 SetOperandAt(1, object); 4743 set_representation(Representation::Tagged()); 4744 SetAllSideEffects(); 4745 } 4746 4747 virtual Representation RequiredInputRepresentation(int index) { 4748 return Representation::Tagged(); 4749 } 4750 4751 HValue* context() { return OperandAt(0); } 4752 HValue* enumerable() { return OperandAt(1); } 4753 4754 virtual void PrintDataTo(StringStream* stream); 4755 4756 virtual HType CalculateInferredType() { 4757 return HType::Tagged(); 4758 } 4759 4760 DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap); 4761 }; 4762 4763 4764 class HForInCacheArray : public HTemplateInstruction<2> { 4765 public: 4766 HForInCacheArray(HValue* enumerable, 4767 HValue* keys, 4768 int idx) : idx_(idx) { 4769 SetOperandAt(0, enumerable); 4770 SetOperandAt(1, keys); 4771 set_representation(Representation::Tagged()); 4772 } 4773 4774 virtual Representation RequiredInputRepresentation(int index) { 4775 return Representation::Tagged(); 4776 } 4777 4778 HValue* enumerable() { return OperandAt(0); } 4779 HValue* map() { return OperandAt(1); } 4780 int idx() { return idx_; } 4781 4782 HForInCacheArray* index_cache() { 4783 return index_cache_; 4784 } 4785 4786 void set_index_cache(HForInCacheArray* index_cache) { 4787 index_cache_ = index_cache; 4788 } 4789 4790 virtual void PrintDataTo(StringStream* stream); 4791 4792 virtual HType CalculateInferredType() { 4793 return HType::Tagged(); 4794 } 4795 4796 DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray); 4797 4798 private: 4799 int idx_; 4800 HForInCacheArray* index_cache_; 4801 }; 4802 4803 4804 class HLoadFieldByIndex : public HTemplateInstruction<2> { 4805 public: 4806 HLoadFieldByIndex(HValue* object, 4807 HValue* index) { 4808 SetOperandAt(0, object); 4809 SetOperandAt(1, index); 4810 set_representation(Representation::Tagged()); 4811 } 4812 4813 virtual Representation RequiredInputRepresentation(int index) { 4814 return Representation::Tagged(); 4815 } 4816 4817 HValue* object() { return OperandAt(0); } 4818 HValue* index() { return OperandAt(1); } 4819 4820 virtual void PrintDataTo(StringStream* stream); 4821 4822 virtual HType CalculateInferredType() { 4823 return HType::Tagged(); 4824 } 4825 4826 DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex); 4827 }; 4828 4829 4830 #undef DECLARE_INSTRUCTION 4831 #undef DECLARE_CONCRETE_INSTRUCTION 4832 4833 } } // namespace v8::internal 4834 4835 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ 4836