hydrogen-instructions.h revision b8e0da25ee8efac3bb05cd6b2730aafbd96119f4
1// Copyright 2010 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#include "code-stubs.h" 33#include "string-stream.h" 34#include "zone.h" 35 36namespace v8 { 37namespace internal { 38 39// Forward declarations. 40class HBasicBlock; 41class HEnvironment; 42class HInstruction; 43class HLoopInformation; 44class HValue; 45class LInstruction; 46class LChunkBuilder; 47 48 49// Type hierarchy: 50// 51// HValue 52// HInstruction 53// HAccessArgumentsAt 54// HApplyArguments 55// HArgumentsElements 56// HArgumentsLength 57// HArgumentsObject 58// HBinaryOperation 59// HArithmeticBinaryOperation 60// HAdd 61// HDiv 62// HMod 63// HMul 64// HSub 65// HBitwiseBinaryOperation 66// HBitAnd 67// HBitOr 68// HBitXor 69// HSar 70// HShl 71// HShr 72// HBoundsCheck 73// HCompare 74// HCompareJSObjectEq 75// HInstanceOf 76// HInstanceOfKnownGlobal 77// HLoadKeyed 78// HLoadKeyedFastElement 79// HLoadKeyedGeneric 80// HPower 81// HStoreNamed 82// HStoreNamedField 83// HStoreNamedGeneric 84// HBlockEntry 85// HCall 86// HCallConstantFunction 87// HCallFunction 88// HCallGlobal 89// HCallKeyed 90// HCallKnownGlobal 91// HCallNamed 92// HCallNew 93// HCallRuntime 94// HCallStub 95// HCheckPrototypeMaps 96// HConstant 97// HControlInstruction 98// HDeoptimize 99// HGoto 100// HUnaryControlInstruction 101// HBranch 102// HCompareMapAndBranch 103// HReturn 104// HThrow 105// HEnterInlined 106// HFunctionLiteral 107// HGlobalObject 108// HGlobalReceiver 109// HLeaveInlined 110// HLoadContextSlot 111// HLoadGlobal 112// HMaterializedLiteral 113// HArrayLiteral 114// HObjectLiteral 115// HRegExpLiteral 116// HOsrEntry 117// HParameter 118// HSimulate 119// HStackCheck 120// HStoreKeyed 121// HStoreKeyedFastElement 122// HStoreKeyedGeneric 123// HUnaryOperation 124// HBitNot 125// HChange 126// HCheckFunction 127// HCheckInstanceType 128// HCheckMap 129// HCheckNonSmi 130// HCheckSmi 131// HDeleteProperty 132// HFixedArrayLength 133// HJSArrayLength 134// HLoadElements 135// HTypeofIs 136// HLoadNamedField 137// HLoadNamedGeneric 138// HLoadFunctionPrototype 139// HPushArgument 140// HTypeof 141// HUnaryMathOperation 142// HUnaryPredicate 143// HClassOfTest 144// HHasCachedArrayIndex 145// HHasInstanceType 146// HIsNull 147// HIsObject 148// HIsSmi 149// HValueOf 150// HUnknownOSRValue 151// HPhi 152 153#define HYDROGEN_ALL_INSTRUCTION_LIST(V) \ 154 V(ArithmeticBinaryOperation) \ 155 V(BinaryOperation) \ 156 V(BitwiseBinaryOperation) \ 157 V(Call) \ 158 V(ControlInstruction) \ 159 V(Instruction) \ 160 V(LoadKeyed) \ 161 V(MaterializedLiteral) \ 162 V(Phi) \ 163 V(StoreKeyed) \ 164 V(StoreNamed) \ 165 V(UnaryControlInstruction) \ 166 V(UnaryOperation) \ 167 HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) 168 169 170#define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \ 171 V(AccessArgumentsAt) \ 172 V(Add) \ 173 V(ApplyArguments) \ 174 V(ArgumentsElements) \ 175 V(ArgumentsLength) \ 176 V(ArgumentsObject) \ 177 V(ArrayLiteral) \ 178 V(BitAnd) \ 179 V(BitNot) \ 180 V(BitOr) \ 181 V(BitXor) \ 182 V(BlockEntry) \ 183 V(BoundsCheck) \ 184 V(Branch) \ 185 V(CallConstantFunction) \ 186 V(CallFunction) \ 187 V(CallGlobal) \ 188 V(CallKeyed) \ 189 V(CallKnownGlobal) \ 190 V(CallNamed) \ 191 V(CallNew) \ 192 V(CallRuntime) \ 193 V(CallStub) \ 194 V(Change) \ 195 V(CheckFunction) \ 196 V(CheckInstanceType) \ 197 V(CheckMap) \ 198 V(CheckNonSmi) \ 199 V(CheckPrototypeMaps) \ 200 V(CheckSmi) \ 201 V(Compare) \ 202 V(CompareJSObjectEq) \ 203 V(CompareMapAndBranch) \ 204 V(Constant) \ 205 V(DeleteProperty) \ 206 V(Deoptimize) \ 207 V(Div) \ 208 V(EnterInlined) \ 209 V(FixedArrayLength) \ 210 V(FunctionLiteral) \ 211 V(GlobalObject) \ 212 V(GlobalReceiver) \ 213 V(Goto) \ 214 V(InstanceOf) \ 215 V(InstanceOfKnownGlobal) \ 216 V(IsNull) \ 217 V(IsObject) \ 218 V(IsSmi) \ 219 V(HasInstanceType) \ 220 V(HasCachedArrayIndex) \ 221 V(JSArrayLength) \ 222 V(ClassOfTest) \ 223 V(LeaveInlined) \ 224 V(LoadContextSlot) \ 225 V(LoadElements) \ 226 V(LoadGlobal) \ 227 V(LoadKeyedFastElement) \ 228 V(LoadKeyedGeneric) \ 229 V(LoadNamedField) \ 230 V(LoadNamedGeneric) \ 231 V(LoadFunctionPrototype) \ 232 V(Mod) \ 233 V(Mul) \ 234 V(ObjectLiteral) \ 235 V(OsrEntry) \ 236 V(Parameter) \ 237 V(Power) \ 238 V(PushArgument) \ 239 V(RegExpLiteral) \ 240 V(Return) \ 241 V(Sar) \ 242 V(Shl) \ 243 V(Shr) \ 244 V(Simulate) \ 245 V(StackCheck) \ 246 V(StoreGlobal) \ 247 V(StoreKeyedFastElement) \ 248 V(StoreKeyedGeneric) \ 249 V(StoreNamedField) \ 250 V(StoreNamedGeneric) \ 251 V(Sub) \ 252 V(Throw) \ 253 V(Typeof) \ 254 V(TypeofIs) \ 255 V(UnaryMathOperation) \ 256 V(UnknownOSRValue) \ 257 V(ValueOf) 258 259#define GVN_FLAG_LIST(V) \ 260 V(Calls) \ 261 V(InobjectFields) \ 262 V(BackingStoreFields) \ 263 V(ArrayElements) \ 264 V(GlobalVars) \ 265 V(Maps) \ 266 V(ArrayLengths) \ 267 V(FunctionPrototypes) \ 268 V(OsrEntries) 269 270#define DECLARE_INSTRUCTION(type) \ 271 virtual bool Is##type() const { return true; } \ 272 static H##type* cast(HValue* value) { \ 273 ASSERT(value->Is##type()); \ 274 return reinterpret_cast<H##type*>(value); \ 275 } \ 276 Opcode opcode() const { return HValue::k##type; } 277 278 279#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \ 280 virtual LInstruction* CompileToLithium(LChunkBuilder* builder); \ 281 virtual const char* Mnemonic() const { return mnemonic; } \ 282 DECLARE_INSTRUCTION(type) 283 284 285 286template<int kSize> 287class HOperandVector : public EmbeddedVector<HValue*, kSize> { 288 public: 289 HOperandVector() : EmbeddedVector<HValue*, kSize>(NULL) { } 290}; 291 292 293class Range: public ZoneObject { 294 public: 295 Range() : lower_(kMinInt), 296 upper_(kMaxInt), 297 next_(NULL), 298 can_be_minus_zero_(false) { } 299 300 Range(int32_t lower, int32_t upper) 301 : lower_(lower), upper_(upper), next_(NULL), can_be_minus_zero_(false) { } 302 303 bool IsInSmiRange() const { 304 return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue; 305 } 306 void KeepOrder(); 307 void Verify() const; 308 int32_t upper() const { return upper_; } 309 int32_t lower() const { return lower_; } 310 Range* next() const { return next_; } 311 Range* CopyClearLower() const { return new Range(kMinInt, upper_); } 312 Range* CopyClearUpper() const { return new Range(lower_, kMaxInt); } 313 void ClearLower() { lower_ = kMinInt; } 314 void ClearUpper() { upper_ = kMaxInt; } 315 Range* Copy() const { return new Range(lower_, upper_); } 316 bool IsMostGeneric() const { return lower_ == kMinInt && upper_ == kMaxInt; } 317 int32_t Mask() const; 318 void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; } 319 bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; } 320 bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; } 321 bool CanBeNegative() const { return lower_ < 0; } 322 bool Includes(int value) const { 323 return lower_ <= value && upper_ >= value; 324 } 325 326 void Sar(int32_t value) { 327 int32_t bits = value & 0x1F; 328 lower_ = lower_ >> bits; 329 upper_ = upper_ >> bits; 330 set_can_be_minus_zero(false); 331 } 332 333 void Shl(int32_t value) { 334 int32_t bits = value & 0x1F; 335 int old_lower = lower_; 336 int old_upper = upper_; 337 lower_ = lower_ << bits; 338 upper_ = upper_ << bits; 339 if (old_lower != lower_ >> bits || old_upper != upper_ >> bits) { 340 upper_ = kMaxInt; 341 lower_ = kMinInt; 342 } 343 set_can_be_minus_zero(false); 344 } 345 346 // Adds a constant to the lower and upper bound of the range. 347 void AddConstant(int32_t value); 348 349 void StackUpon(Range* other) { 350 Intersect(other); 351 next_ = other; 352 } 353 354 void Intersect(Range* other) { 355 upper_ = Min(upper_, other->upper_); 356 lower_ = Max(lower_, other->lower_); 357 bool b = CanBeMinusZero() && other->CanBeMinusZero(); 358 set_can_be_minus_zero(b); 359 } 360 361 void Union(Range* other) { 362 upper_ = Max(upper_, other->upper_); 363 lower_ = Min(lower_, other->lower_); 364 bool b = CanBeMinusZero() || other->CanBeMinusZero(); 365 set_can_be_minus_zero(b); 366 } 367 368 // Compute a new result range and return true, if the operation 369 // can overflow. 370 bool AddAndCheckOverflow(Range* other); 371 bool SubAndCheckOverflow(Range* other); 372 bool MulAndCheckOverflow(Range* other); 373 374 private: 375 int32_t lower_; 376 int32_t upper_; 377 Range* next_; 378 bool can_be_minus_zero_; 379}; 380 381 382class Representation { 383 public: 384 enum Kind { 385 kNone, 386 kTagged, 387 kDouble, 388 kInteger32, 389 kNumRepresentations 390 }; 391 392 Representation() : kind_(kNone) { } 393 394 static Representation None() { return Representation(kNone); } 395 static Representation Tagged() { return Representation(kTagged); } 396 static Representation Integer32() { return Representation(kInteger32); } 397 static Representation Double() { return Representation(kDouble); } 398 399 bool Equals(const Representation& other) const { 400 return kind_ == other.kind_; 401 } 402 403 Kind kind() const { return kind_; } 404 bool IsNone() const { return kind_ == kNone; } 405 bool IsTagged() const { return kind_ == kTagged; } 406 bool IsInteger32() const { return kind_ == kInteger32; } 407 bool IsDouble() const { return kind_ == kDouble; } 408 bool IsSpecialization() const { 409 return kind_ == kInteger32 || kind_ == kDouble; 410 } 411 const char* Mnemonic() const; 412 413 private: 414 explicit Representation(Kind k) : kind_(k) { } 415 416 Kind kind_; 417}; 418 419 420class HType { 421 public: 422 HType() : type_(kUninitialized) { } 423 424 static HType Tagged() { return HType(kTagged); } 425 static HType TaggedPrimitive() { return HType(kTaggedPrimitive); } 426 static HType TaggedNumber() { return HType(kTaggedNumber); } 427 static HType Smi() { return HType(kSmi); } 428 static HType HeapNumber() { return HType(kHeapNumber); } 429 static HType String() { return HType(kString); } 430 static HType Boolean() { return HType(kBoolean); } 431 static HType NonPrimitive() { return HType(kNonPrimitive); } 432 static HType JSArray() { return HType(kJSArray); } 433 static HType JSObject() { return HType(kJSObject); } 434 static HType Uninitialized() { return HType(kUninitialized); } 435 436 // Return the weakest (least precise) common type. 437 HType Combine(HType other) { 438 return HType(static_cast<Type>(type_ & other.type_)); 439 } 440 441 bool Equals(const HType& other) { 442 return type_ == other.type_; 443 } 444 445 bool IsSubtypeOf(const HType& other) { 446 return Combine(other).Equals(other); 447 } 448 449 bool IsTagged() { 450 ASSERT(type_ != kUninitialized); 451 return ((type_ & kTagged) == kTagged); 452 } 453 454 bool IsTaggedPrimitive() { 455 ASSERT(type_ != kUninitialized); 456 return ((type_ & kTaggedPrimitive) == kTaggedPrimitive); 457 } 458 459 bool IsTaggedNumber() { 460 ASSERT(type_ != kUninitialized); 461 return ((type_ & kTaggedNumber) == kTaggedNumber); 462 } 463 464 bool IsSmi() { 465 ASSERT(type_ != kUninitialized); 466 return ((type_ & kSmi) == kSmi); 467 } 468 469 bool IsHeapNumber() { 470 ASSERT(type_ != kUninitialized); 471 return ((type_ & kHeapNumber) == kHeapNumber); 472 } 473 474 bool IsString() { 475 ASSERT(type_ != kUninitialized); 476 return ((type_ & kString) == kString); 477 } 478 479 bool IsBoolean() { 480 ASSERT(type_ != kUninitialized); 481 return ((type_ & kBoolean) == kBoolean); 482 } 483 484 bool IsNonPrimitive() { 485 ASSERT(type_ != kUninitialized); 486 return ((type_ & kNonPrimitive) == kNonPrimitive); 487 } 488 489 bool IsJSArray() { 490 ASSERT(type_ != kUninitialized); 491 return ((type_ & kJSArray) == kJSArray); 492 } 493 494 bool IsJSObject() { 495 ASSERT(type_ != kUninitialized); 496 return ((type_ & kJSObject) == kJSObject); 497 } 498 499 bool IsUninitialized() { 500 return type_ == kUninitialized; 501 } 502 503 static HType TypeFromValue(Handle<Object> value); 504 505 const char* ToString(); 506 const char* ToShortString(); 507 508 private: 509 enum Type { 510 kTagged = 0x1, // 0000 0000 0000 0001 511 kTaggedPrimitive = 0x5, // 0000 0000 0000 0101 512 kTaggedNumber = 0xd, // 0000 0000 0000 1101 513 kSmi = 0x1d, // 0000 0000 0001 1101 514 kHeapNumber = 0x2d, // 0000 0000 0010 1101 515 kString = 0x45, // 0000 0000 0100 0101 516 kBoolean = 0x85, // 0000 0000 1000 0101 517 kNonPrimitive = 0x101, // 0000 0001 0000 0001 518 kJSObject = 0x301, // 0000 0011 0000 0001 519 kJSArray = 0x701, // 0000 0111 1000 0001 520 kUninitialized = 0x1fff // 0001 1111 1111 1111 521 }; 522 523 explicit HType(Type t) : type_(t) { } 524 525 Type type_; 526}; 527 528 529class HValue: public ZoneObject { 530 public: 531 static const int kNoNumber = -1; 532 533 // There must be one corresponding kDepends flag for every kChanges flag and 534 // the order of the kChanges flags must be exactly the same as of the kDepends 535 // flags. 536 enum Flag { 537 // Declare global value numbering flags. 538 #define DECLARE_DO(type) kChanges##type, kDependsOn##type, 539 GVN_FLAG_LIST(DECLARE_DO) 540 #undef DECLARE_DO 541 kFlexibleRepresentation, 542 kUseGVN, 543 kCanOverflow, 544 kBailoutOnMinusZero, 545 kCanBeDivByZero, 546 kIsArguments, 547 kTruncatingToInt32, 548 kLastFlag = kTruncatingToInt32 549 }; 550 551 STATIC_ASSERT(kLastFlag < kBitsPerInt); 552 553 static const int kChangesToDependsFlagsLeftShift = 1; 554 555 static int ChangesFlagsMask() { 556 int result = 0; 557 // Create changes mask. 558#define DECLARE_DO(type) result |= (1 << kChanges##type); 559 GVN_FLAG_LIST(DECLARE_DO) 560#undef DECLARE_DO 561 return result; 562 } 563 564 static int DependsFlagsMask() { 565 return ConvertChangesToDependsFlags(ChangesFlagsMask()); 566 } 567 568 static int ConvertChangesToDependsFlags(int flags) { 569 return flags << kChangesToDependsFlagsLeftShift; 570 } 571 572 // A flag mask to mark an instruction as having arbitrary side effects. 573 static int AllSideEffects() { 574 return ChangesFlagsMask() & ~(1 << kChangesOsrEntries); 575 } 576 577 static HValue* cast(HValue* value) { return value; } 578 579 enum Opcode { 580 // Declare a unique enum value for each hydrogen instruction. 581 #define DECLARE_DO(type) k##type, 582 HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO) 583 #undef DECLARE_DO 584 kMaxInstructionClass 585 }; 586 587 HValue() : block_(NULL), 588 id_(kNoNumber), 589 uses_(2), 590 type_(HType::Tagged()), 591 range_(NULL), 592 flags_(0) {} 593 virtual ~HValue() {} 594 595 HBasicBlock* block() const { return block_; } 596 void SetBlock(HBasicBlock* block); 597 598 int id() const { return id_; } 599 void set_id(int id) { id_ = id; } 600 601 const ZoneList<HValue*>* uses() const { return &uses_; } 602 603 virtual bool EmitAtUses() const { return false; } 604 Representation representation() const { return representation_; } 605 void ChangeRepresentation(Representation r) { 606 // Representation was already set and is allowed to be changed. 607 ASSERT(!representation_.IsNone()); 608 ASSERT(!r.IsNone()); 609 ASSERT(CheckFlag(kFlexibleRepresentation)); 610 RepresentationChanged(r); 611 representation_ = r; 612 } 613 614 HType type() const { return type_; } 615 void set_type(HType type) { 616 ASSERT(uses_.length() == 0); 617 type_ = type; 618 } 619 620 // An operation needs to override this function iff: 621 // 1) it can produce an int32 output. 622 // 2) the true value of its output can potentially be minus zero. 623 // The implementation must set a flag so that it bails out in the case where 624 // it would otherwise output what should be a minus zero as an int32 zero. 625 // If the operation also exists in a form that takes int32 and outputs int32 626 // then the operation should return its input value so that we can propagate 627 // back. There are two operations that need to propagate back to more than 628 // one input. They are phi and binary add. They always return NULL and 629 // expect the caller to take care of things. 630 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) { 631 visited->Add(id()); 632 return NULL; 633 } 634 635 bool HasSideEffects() const { 636 return (flags_ & AllSideEffects()) != 0; 637 } 638 bool IsDefinedAfter(HBasicBlock* other) const; 639 640 // Operands. 641 virtual int OperandCount() const { return 0; } 642 virtual HValue* OperandAt(int index) const { 643 UNREACHABLE(); 644 return NULL; 645 } 646 void SetOperandAt(int index, HValue* value); 647 648 int LookupOperandIndex(int occurrence_index, HValue* op) const; 649 bool UsesMultipleTimes(HValue* op) const; 650 651 void ReplaceAndDelete(HValue* other); 652 void ReplaceValue(HValue* other); 653 void ReplaceAtUse(HValue* use, HValue* other); 654 void ReplaceFirstAtUse(HValue* use, HValue* other, Representation r); 655 bool HasNoUses() const { return uses_.is_empty(); } 656 void ClearOperands(); 657 void Delete(); 658 659 int flags() const { return flags_; } 660 void SetFlagMask(int mask) { flags_ |= mask; } 661 void SetFlag(Flag f) { SetFlagMask(1 << f); } 662 void ClearFlagMask(int mask) { flags_ &= ~mask; } 663 void ClearFlag(Flag f) { ClearFlagMask(1 << f); } 664 bool CheckFlag(Flag f) const { return CheckFlagMask(1 << f); } 665 bool CheckFlagMask(int mask) const { return (flags_ & mask) != 0; } 666 667 Range* range() const { return range_; } 668 bool HasRange() const { return range_ != NULL; } 669 void AddNewRange(Range* r); 670 void RemoveLastAddedRange(); 671 void ComputeInitialRange(); 672 673 // Representation helpers. 674 virtual Representation RequiredInputRepresentation(int index) const { 675 return Representation::None(); 676 } 677 virtual Representation InferredRepresentation() const { 678 return representation(); 679 } 680 681 // This gives the instruction an opportunity to replace itself with an 682 // instruction that does the same in some better way. To replace an 683 // instruction with a new one, first add the new instruction to the graph, 684 // then return it. Return NULL to have the instruction deleted. 685 virtual HValue* Canonicalize() { return this; } 686 687 // Declare virtual type testers. 688#define DECLARE_DO(type) virtual bool Is##type() const { return false; } 689 HYDROGEN_ALL_INSTRUCTION_LIST(DECLARE_DO) 690#undef DECLARE_DO 691 692 bool Equals(HValue* other) const; 693 virtual intptr_t Hashcode() const; 694 695 // Printing support. 696 virtual void PrintTo(StringStream* stream) const = 0; 697 void PrintNameTo(StringStream* stream); 698 static void PrintTypeTo(HType type, StringStream* stream); 699 700 virtual const char* Mnemonic() const = 0; 701 virtual Opcode opcode() const = 0; 702 703 // Updated the inferred type of this instruction and returns true if 704 // it has changed. 705 bool UpdateInferredType(); 706 707 virtual HType CalculateInferredType() const; 708 709 // Helper for type conversions used by normal and phi instructions. 710 void InsertInputConversion(HInstruction* previous, int index, HType type); 711 712#ifdef DEBUG 713 virtual void Verify() const = 0; 714#endif 715 716 protected: 717 virtual bool DataEquals(HValue* other) const { return true; } 718 virtual void RepresentationChanged(Representation to) { } 719 virtual Range* InferRange(); 720 virtual void DeleteFromGraph() = 0; 721 virtual void InternalSetOperandAt(int index, HValue* value) { UNREACHABLE(); } 722 void clear_block() { 723 ASSERT(block_ != NULL); 724 block_ = NULL; 725 } 726 727 void set_representation(Representation r) { 728 // Representation is set-once. 729 ASSERT(representation_.IsNone() && !r.IsNone()); 730 representation_ = r; 731 } 732 733 private: 734 void InternalReplaceAtUse(HValue* use, HValue* other); 735 void RegisterUse(int index, HValue* new_value); 736 737 HBasicBlock* block_; 738 739 // The id of this instruction in the hydrogen graph, assigned when first 740 // added to the graph. Reflects creation order. 741 int id_; 742 743 Representation representation_; 744 ZoneList<HValue*> uses_; 745 HType type_; 746 Range* range_; 747 int flags_; 748 749 DISALLOW_COPY_AND_ASSIGN(HValue); 750}; 751 752 753class HInstruction: public HValue { 754 public: 755 HInstruction* next() const { return next_; } 756 HInstruction* previous() const { return previous_; } 757 758 void PrintTo(StringStream* stream) const; 759 virtual void PrintDataTo(StringStream* stream) const {} 760 761 bool IsLinked() const { return block() != NULL; } 762 void Unlink(); 763 void InsertBefore(HInstruction* next); 764 void InsertAfter(HInstruction* previous); 765 766 int position() const { return position_; } 767 bool has_position() const { return position_ != RelocInfo::kNoPosition; } 768 void set_position(int position) { position_ = position; } 769 770 virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0; 771 772#ifdef DEBUG 773 virtual void Verify() const; 774#endif 775 776 // Returns whether this is some kind of deoptimizing check 777 // instruction. 778 virtual bool IsCheckInstruction() const { return false; } 779 780 DECLARE_INSTRUCTION(Instruction) 781 782 protected: 783 HInstruction() 784 : next_(NULL), 785 previous_(NULL), 786 position_(RelocInfo::kNoPosition) { 787 SetFlag(kDependsOnOsrEntries); 788 } 789 790 virtual void DeleteFromGraph() { Unlink(); } 791 792 private: 793 void InitializeAsFirst(HBasicBlock* block) { 794 ASSERT(!IsLinked()); 795 SetBlock(block); 796 } 797 798 HInstruction* next_; 799 HInstruction* previous_; 800 int position_; 801 802 friend class HBasicBlock; 803}; 804 805 806class HBlockEntry: public HInstruction { 807 public: 808 DECLARE_CONCRETE_INSTRUCTION(BlockEntry, "block_entry") 809}; 810 811 812class HControlInstruction: public HInstruction { 813 public: 814 virtual HBasicBlock* FirstSuccessor() const { return NULL; } 815 virtual HBasicBlock* SecondSuccessor() const { return NULL; } 816 817 DECLARE_INSTRUCTION(ControlInstruction) 818}; 819 820 821class HDeoptimize: public HControlInstruction { 822 public: 823 DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize") 824}; 825 826 827class HGoto: public HControlInstruction { 828 public: 829 explicit HGoto(HBasicBlock* destination) 830 : destination_(destination), 831 include_stack_check_(false) {} 832 833 virtual HBasicBlock* FirstSuccessor() const { return destination_; } 834 void set_include_stack_check(bool include_stack_check) { 835 include_stack_check_ = include_stack_check; 836 } 837 bool include_stack_check() const { return include_stack_check_; } 838 839 virtual void PrintDataTo(StringStream* stream) const; 840 841 DECLARE_CONCRETE_INSTRUCTION(Goto, "goto") 842 843 private: 844 HBasicBlock* destination_; 845 bool include_stack_check_; 846}; 847 848 849class HUnaryControlInstruction: public HControlInstruction { 850 public: 851 explicit HUnaryControlInstruction(HValue* value) { 852 SetOperandAt(0, value); 853 } 854 855 virtual Representation RequiredInputRepresentation(int index) const { 856 return Representation::Tagged(); 857 } 858 859 HValue* value() const { return OperandAt(0); } 860 virtual int OperandCount() const { return 1; } 861 virtual HValue* OperandAt(int index) const { return operands_[index]; } 862 863 DECLARE_INSTRUCTION(UnaryControlInstruction) 864 865 protected: 866 virtual void InternalSetOperandAt(int index, HValue* value) { 867 operands_[index] = value; 868 } 869 870 private: 871 HOperandVector<1> operands_; 872}; 873 874 875class HBranch: public HUnaryControlInstruction { 876 public: 877 HBranch(HBasicBlock* true_destination, 878 HBasicBlock* false_destination, 879 HValue* boolean_value) 880 : HUnaryControlInstruction(boolean_value), 881 true_destination_(true_destination), 882 false_destination_(false_destination) { 883 ASSERT(true_destination != NULL && false_destination != NULL); 884 } 885 886 virtual Representation RequiredInputRepresentation(int index) const { 887 return Representation::None(); 888 } 889 890 virtual HBasicBlock* FirstSuccessor() const { return true_destination_; } 891 virtual HBasicBlock* SecondSuccessor() const { return false_destination_; } 892 893 virtual void PrintDataTo(StringStream* stream) const; 894 895 DECLARE_CONCRETE_INSTRUCTION(Branch, "branch") 896 897 private: 898 HBasicBlock* true_destination_; 899 HBasicBlock* false_destination_; 900}; 901 902 903class HCompareMapAndBranch: public HUnaryControlInstruction { 904 public: 905 HCompareMapAndBranch(HValue* result, 906 Handle<Map> map, 907 HBasicBlock* true_destination, 908 HBasicBlock* false_destination) 909 : HUnaryControlInstruction(result), 910 map_(map), 911 true_destination_(true_destination), 912 false_destination_(false_destination) { 913 ASSERT(true_destination != NULL); 914 ASSERT(false_destination != NULL); 915 ASSERT(!map.is_null()); 916 } 917 918 virtual HBasicBlock* FirstSuccessor() const { return true_destination_; } 919 virtual HBasicBlock* SecondSuccessor() const { return false_destination_; } 920 921 HBasicBlock* true_destination() const { return true_destination_; } 922 HBasicBlock* false_destination() const { return false_destination_; } 923 924 virtual void PrintDataTo(StringStream* stream) const; 925 926 Handle<Map> map() const { return map_; } 927 928 DECLARE_CONCRETE_INSTRUCTION(CompareMapAndBranch, "compare_map_and_branch") 929 930 private: 931 Handle<Map> map_; 932 HBasicBlock* true_destination_; 933 HBasicBlock* false_destination_; 934}; 935 936 937class HReturn: public HUnaryControlInstruction { 938 public: 939 explicit HReturn(HValue* result) : HUnaryControlInstruction(result) { } 940 941 virtual void PrintDataTo(StringStream* stream) const; 942 943 DECLARE_CONCRETE_INSTRUCTION(Return, "return") 944}; 945 946 947class HThrow: public HUnaryControlInstruction { 948 public: 949 explicit HThrow(HValue* value) : HUnaryControlInstruction(value) { } 950 951 virtual void PrintDataTo(StringStream* stream) const; 952 953 DECLARE_CONCRETE_INSTRUCTION(Throw, "throw") 954}; 955 956 957class HUnaryOperation: public HInstruction { 958 public: 959 explicit HUnaryOperation(HValue* value) { 960 SetOperandAt(0, value); 961 } 962 963 HValue* value() const { return OperandAt(0); } 964 virtual void PrintDataTo(StringStream* stream) const; 965 virtual int OperandCount() const { return 1; } 966 virtual HValue* OperandAt(int index) const { return operands_[index]; } 967 968 DECLARE_INSTRUCTION(UnaryOperation) 969 970 protected: 971 virtual void InternalSetOperandAt(int index, HValue* value) { 972 operands_[index] = value; 973 } 974 975 private: 976 HOperandVector<1> operands_; 977}; 978 979 980class HChange: public HUnaryOperation { 981 public: 982 HChange(HValue* value, 983 Representation from, 984 Representation to) 985 : HUnaryOperation(value), from_(from), to_(to) { 986 ASSERT(!from.IsNone() && !to.IsNone()); 987 ASSERT(!from.Equals(to)); 988 set_representation(to); 989 SetFlag(kUseGVN); 990 991 if (from.IsInteger32() && to.IsTagged() && value->range() != NULL && 992 value->range()->IsInSmiRange()) { 993 set_type(HType::Smi()); 994 } 995 } 996 997 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); 998 999 Representation from() const { return from_; } 1000 Representation to() const { return to_; } 1001 virtual Representation RequiredInputRepresentation(int index) const { 1002 return from_; 1003 } 1004 1005 bool CanTruncateToInt32() const { 1006 for (int i = 0; i < uses()->length(); ++i) { 1007 if (!uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) return false; 1008 } 1009 return true; 1010 } 1011 1012 virtual void PrintDataTo(StringStream* stream) const; 1013 1014 DECLARE_CONCRETE_INSTRUCTION(Change, 1015 CanTruncateToInt32() ? "truncate" : "change") 1016 1017 protected: 1018 virtual bool DataEquals(HValue* other) const { 1019 if (!other->IsChange()) return false; 1020 HChange* change = HChange::cast(other); 1021 return value() == change->value() 1022 && to().Equals(change->to()) 1023 && CanTruncateToInt32() == change->CanTruncateToInt32(); 1024 } 1025 1026 private: 1027 Representation from_; 1028 Representation to_; 1029}; 1030 1031 1032class HSimulate: public HInstruction { 1033 public: 1034 HSimulate(int ast_id, int pop_count, int environment_length) 1035 : ast_id_(ast_id), 1036 pop_count_(pop_count), 1037 environment_length_(environment_length), 1038 values_(2), 1039 assigned_indexes_(2) {} 1040 virtual ~HSimulate() {} 1041 1042 virtual void PrintDataTo(StringStream* stream) const; 1043 1044 bool HasAstId() const { return ast_id_ != AstNode::kNoNumber; } 1045 int ast_id() const { return ast_id_; } 1046 void set_ast_id(int id) { 1047 ASSERT(!HasAstId()); 1048 ast_id_ = id; 1049 } 1050 1051 int environment_length() const { return environment_length_; } 1052 int pop_count() const { return pop_count_; } 1053 const ZoneList<HValue*>* values() const { return &values_; } 1054 int GetAssignedIndexAt(int index) const { 1055 ASSERT(HasAssignedIndexAt(index)); 1056 return assigned_indexes_[index]; 1057 } 1058 bool HasAssignedIndexAt(int index) const { 1059 return assigned_indexes_[index] != kNoIndex; 1060 } 1061 void AddAssignedValue(int index, HValue* value) { 1062 AddValue(index, value); 1063 } 1064 void AddPushedValue(HValue* value) { 1065 AddValue(kNoIndex, value); 1066 } 1067 virtual int OperandCount() const { return values_.length(); } 1068 virtual HValue* OperandAt(int index) const { return values_[index]; } 1069 1070 DECLARE_CONCRETE_INSTRUCTION(Simulate, "simulate") 1071 1072#ifdef DEBUG 1073 virtual void Verify() const; 1074#endif 1075 1076 protected: 1077 virtual void InternalSetOperandAt(int index, HValue* value) { 1078 values_[index] = value; 1079 } 1080 1081 private: 1082 static const int kNoIndex = -1; 1083 void AddValue(int index, HValue* value) { 1084 assigned_indexes_.Add(index); 1085 // Resize the list of pushed values. 1086 values_.Add(NULL); 1087 // Set the operand through the base method in HValue to make sure that the 1088 // use lists are correctly updated. 1089 SetOperandAt(values_.length() - 1, value); 1090 } 1091 int ast_id_; 1092 int pop_count_; 1093 int environment_length_; 1094 ZoneList<HValue*> values_; 1095 ZoneList<int> assigned_indexes_; 1096}; 1097 1098 1099class HStackCheck: public HInstruction { 1100 public: 1101 HStackCheck() { } 1102 1103 DECLARE_CONCRETE_INSTRUCTION(Throw, "stack_check") 1104}; 1105 1106 1107class HEnterInlined: public HInstruction { 1108 public: 1109 HEnterInlined(Handle<JSFunction> closure, FunctionLiteral* function) 1110 : closure_(closure), function_(function) { 1111 } 1112 1113 virtual void PrintDataTo(StringStream* stream) const; 1114 1115 Handle<JSFunction> closure() const { return closure_; } 1116 FunctionLiteral* function() const { return function_; } 1117 1118 DECLARE_CONCRETE_INSTRUCTION(EnterInlined, "enter_inlined") 1119 1120 private: 1121 Handle<JSFunction> closure_; 1122 FunctionLiteral* function_; 1123}; 1124 1125 1126class HLeaveInlined: public HInstruction { 1127 public: 1128 HLeaveInlined() {} 1129 1130 DECLARE_CONCRETE_INSTRUCTION(LeaveInlined, "leave_inlined") 1131}; 1132 1133 1134class HPushArgument: public HUnaryOperation { 1135 public: 1136 explicit HPushArgument(HValue* value) 1137 : HUnaryOperation(value), argument_index_(-1) { 1138 set_representation(Representation::Tagged()); 1139 } 1140 1141 virtual Representation RequiredInputRepresentation(int index) const { 1142 return Representation::Tagged(); 1143 } 1144 1145 virtual void PrintDataTo(StringStream* stream) const; 1146 HValue* argument() const { return OperandAt(0); } 1147 int argument_index() const { return argument_index_; } 1148 void set_argument_index(int index) { 1149 ASSERT(argument_index_ == -1 || index == argument_index_); 1150 argument_index_ = index; 1151 } 1152 1153 DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push_argument") 1154 1155 private: 1156 int argument_index_; 1157}; 1158 1159 1160class HGlobalObject: public HInstruction { 1161 public: 1162 HGlobalObject() { 1163 set_representation(Representation::Tagged()); 1164 SetFlag(kUseGVN); 1165 SetFlag(kDependsOnCalls); 1166 } 1167 1168 DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global_object") 1169}; 1170 1171 1172class HGlobalReceiver: public HInstruction { 1173 public: 1174 HGlobalReceiver() { 1175 set_representation(Representation::Tagged()); 1176 SetFlag(kUseGVN); 1177 SetFlag(kDependsOnCalls); 1178 } 1179 1180 DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global_receiver") 1181}; 1182 1183 1184class HCall: public HInstruction { 1185 public: 1186 // Construct a call with uninitialized arguments. The argument count 1187 // includes the receiver. 1188 explicit HCall(int count); 1189 1190 virtual HType CalculateInferredType() const { return HType::Tagged(); } 1191 1192 // TODO(3190496): This needs a cleanup. We don't want the arguments 1193 // be operands of the call instruction. This results in bad code quality. 1194 virtual int argument_count() const { return arguments_.length(); } 1195 virtual int OperandCount() const { return argument_count(); } 1196 virtual HValue* OperandAt(int index) const { return arguments_[index]; } 1197 virtual HPushArgument* PushArgumentAt(int index) const { 1198 return HPushArgument::cast(OperandAt(index)); 1199 } 1200 virtual HValue* ArgumentAt(int index) const { 1201 return PushArgumentAt(index)->argument(); 1202 } 1203 virtual void SetArgumentAt(int index, HPushArgument* push_argument); 1204 1205 virtual void PrintDataTo(StringStream* stream) const; 1206 1207 DECLARE_INSTRUCTION(Call) 1208 1209 protected: 1210 virtual void InternalSetOperandAt(int index, HValue* value) { 1211 arguments_[index] = value; 1212 } 1213 1214 int argument_count_; 1215 Vector<HValue*> arguments_; 1216}; 1217 1218 1219class HCallConstantFunction: public HCall { 1220 public: 1221 HCallConstantFunction(Handle<JSFunction> function, int argument_count) 1222 : HCall(argument_count), function_(function) { } 1223 1224 Handle<JSFunction> function() const { return function_; } 1225 bool IsApplyFunction() const { 1226 return function_->code() == Builtins::builtin(Builtins::FunctionApply); 1227 } 1228 1229 virtual void PrintDataTo(StringStream* stream) const; 1230 1231 DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction, "call_constant_function") 1232 1233 private: 1234 Handle<JSFunction> function_; 1235}; 1236 1237 1238class HCallKeyed: public HCall { 1239 public: 1240 HCallKeyed(HValue* key, int argument_count) 1241 : HCall(argument_count + 1) { 1242 SetOperandAt(0, key); 1243 } 1244 1245 virtual Representation RequiredInputRepresentation(int index) const { 1246 return Representation::Tagged(); 1247 } 1248 1249 // TODO(3190496): This is a hack to get an additional operand that 1250 // is not an argument to work with the current setup. This _needs_ a cleanup. 1251 // (see HCall) 1252 virtual void PrintDataTo(StringStream* stream) const; 1253 HValue* key() const { return OperandAt(0); } 1254 virtual int argument_count() const { return arguments_.length() - 1; } 1255 virtual int OperandCount() const { return arguments_.length(); } 1256 virtual HValue* OperandAt(int index) const { return arguments_[index]; } 1257 virtual HPushArgument* PushArgumentAt(int index) const { 1258 return HPushArgument::cast(OperandAt(index + 1)); 1259 } 1260 virtual void SetArgumentAt(int index, HPushArgument* push_argument) { 1261 HCall::SetArgumentAt(index + 1, push_argument); 1262 } 1263 1264 DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call_keyed") 1265}; 1266 1267 1268class HCallNamed: public HCall { 1269 public: 1270 HCallNamed(Handle<String> name, int argument_count) 1271 : HCall(argument_count), name_(name) { } 1272 virtual void PrintDataTo(StringStream* stream) const; 1273 1274 Handle<String> name() const { return name_; } 1275 1276 DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call_named") 1277 1278 private: 1279 Handle<String> name_; 1280}; 1281 1282 1283class HCallFunction: public HCall { 1284 public: 1285 explicit HCallFunction(int argument_count) : HCall(argument_count) { } 1286 1287 DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call_function") 1288}; 1289 1290 1291class HCallGlobal: public HCall { 1292 public: 1293 HCallGlobal(Handle<String> name, int argument_count) 1294 : HCall(argument_count), name_(name) { } 1295 1296 virtual void PrintDataTo(StringStream* stream) const; 1297 1298 Handle<String> name() const { return name_; } 1299 1300 DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call_global") 1301 1302 private: 1303 Handle<String> name_; 1304}; 1305 1306 1307class HCallKnownGlobal: public HCall { 1308 public: 1309 HCallKnownGlobal(Handle<JSFunction> target, 1310 int argument_count) 1311 : HCall(argument_count), target_(target) { } 1312 1313 Handle<JSFunction> target() const { return target_; } 1314 1315 DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call_known_global") 1316 1317 private: 1318 Handle<JSFunction> target_; 1319}; 1320 1321 1322class HCallNew: public HCall { 1323 public: 1324 explicit HCallNew(int argument_count) : HCall(argument_count) { } 1325 1326 virtual Representation RequiredInputRepresentation(int index) const { 1327 return Representation::Tagged(); 1328 } 1329 1330 HValue* constructor() const { return ArgumentAt(0); } 1331 1332 DECLARE_CONCRETE_INSTRUCTION(CallNew, "call_new") 1333}; 1334 1335 1336class HCallRuntime: public HCall { 1337 public: 1338 HCallRuntime(Handle<String> name, 1339 Runtime::Function* c_function, 1340 int argument_count) 1341 : HCall(argument_count), c_function_(c_function), name_(name) { } 1342 virtual void PrintDataTo(StringStream* stream) const; 1343 1344 Runtime::Function* function() const { return c_function_; } 1345 Handle<String> name() const { return name_; } 1346 1347 DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call_runtime") 1348 1349 private: 1350 Runtime::Function* c_function_; 1351 Handle<String> name_; 1352}; 1353 1354 1355class HJSArrayLength: public HUnaryOperation { 1356 public: 1357 explicit HJSArrayLength(HValue* value) : HUnaryOperation(value) { 1358 // The length of an array is stored as a tagged value in the array 1359 // object. It is guaranteed to be 32 bit integer, but it can be 1360 // represented as either a smi or heap number. 1361 set_representation(Representation::Tagged()); 1362 SetFlag(kDependsOnArrayLengths); 1363 SetFlag(kUseGVN); 1364 } 1365 1366 virtual Representation RequiredInputRepresentation(int index) const { 1367 return Representation::Tagged(); 1368 } 1369 1370 DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js_array_length") 1371}; 1372 1373 1374class HFixedArrayLength: public HUnaryOperation { 1375 public: 1376 explicit HFixedArrayLength(HValue* value) : HUnaryOperation(value) { 1377 set_representation(Representation::Tagged()); 1378 SetFlag(kDependsOnArrayLengths); 1379 SetFlag(kUseGVN); 1380 } 1381 1382 virtual Representation RequiredInputRepresentation(int index) const { 1383 return Representation::Tagged(); 1384 } 1385 1386 DECLARE_CONCRETE_INSTRUCTION(FixedArrayLength, "fixed_array_length") 1387}; 1388 1389 1390class HBitNot: public HUnaryOperation { 1391 public: 1392 explicit HBitNot(HValue* value) : HUnaryOperation(value) { 1393 set_representation(Representation::Integer32()); 1394 SetFlag(kUseGVN); 1395 SetFlag(kTruncatingToInt32); 1396 } 1397 1398 virtual Representation RequiredInputRepresentation(int index) const { 1399 return Representation::Integer32(); 1400 } 1401 virtual HType CalculateInferredType() const; 1402 1403 DECLARE_CONCRETE_INSTRUCTION(BitNot, "bit_not") 1404}; 1405 1406 1407class HUnaryMathOperation: public HUnaryOperation { 1408 public: 1409 HUnaryMathOperation(HValue* value, BuiltinFunctionId op) 1410 : HUnaryOperation(value), op_(op) { 1411 switch (op) { 1412 case kMathFloor: 1413 case kMathRound: 1414 case kMathCeil: 1415 set_representation(Representation::Integer32()); 1416 break; 1417 case kMathAbs: 1418 set_representation(Representation::Tagged()); 1419 SetFlag(kFlexibleRepresentation); 1420 break; 1421 case kMathSqrt: 1422 case kMathPowHalf: 1423 case kMathLog: 1424 case kMathSin: 1425 case kMathCos: 1426 set_representation(Representation::Double()); 1427 break; 1428 default: 1429 UNREACHABLE(); 1430 } 1431 SetFlag(kUseGVN); 1432 } 1433 1434 virtual void PrintDataTo(StringStream* stream) const; 1435 1436 virtual HType CalculateInferredType() const; 1437 1438 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); 1439 1440 virtual Representation RequiredInputRepresentation(int index) const { 1441 switch (op_) { 1442 case kMathFloor: 1443 case kMathRound: 1444 case kMathCeil: 1445 case kMathSqrt: 1446 case kMathPowHalf: 1447 case kMathLog: 1448 case kMathSin: 1449 case kMathCos: 1450 return Representation::Double(); 1451 break; 1452 case kMathAbs: 1453 return representation(); 1454 break; 1455 default: 1456 return Representation::None(); 1457 } 1458 } 1459 1460 virtual HValue* Canonicalize() { 1461 // If the input is integer32 then we replace the floor instruction 1462 // with its inputs. This happens before the representation changes are 1463 // introduced. 1464 if (op() == kMathFloor) { 1465 if (value()->representation().IsInteger32()) return value(); 1466 } 1467 return this; 1468 } 1469 1470 BuiltinFunctionId op() const { return op_; } 1471 const char* OpName() const; 1472 1473 DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation, "unary_math_operation") 1474 1475 protected: 1476 virtual bool DataEquals(HValue* other) const { 1477 HUnaryMathOperation* b = HUnaryMathOperation::cast(other); 1478 return op_ == b->op(); 1479 } 1480 1481 private: 1482 BuiltinFunctionId op_; 1483}; 1484 1485 1486class HLoadElements: public HUnaryOperation { 1487 public: 1488 explicit HLoadElements(HValue* value) : HUnaryOperation(value) { 1489 set_representation(Representation::Tagged()); 1490 SetFlag(kUseGVN); 1491 SetFlag(kDependsOnMaps); 1492 } 1493 1494 virtual Representation RequiredInputRepresentation(int index) const { 1495 return Representation::Tagged(); 1496 } 1497 1498 DECLARE_CONCRETE_INSTRUCTION(LoadElements, "load-elements") 1499}; 1500 1501 1502class HCheckMap: public HUnaryOperation { 1503 public: 1504 HCheckMap(HValue* value, Handle<Map> map) 1505 : HUnaryOperation(value), map_(map) { 1506 set_representation(Representation::Tagged()); 1507 SetFlag(kUseGVN); 1508 SetFlag(kDependsOnMaps); 1509 } 1510 1511 virtual bool IsCheckInstruction() const { return true; } 1512 1513 virtual Representation RequiredInputRepresentation(int index) const { 1514 return Representation::Tagged(); 1515 } 1516 virtual void PrintDataTo(StringStream* stream) const; 1517 virtual HType CalculateInferredType() const; 1518 1519#ifdef DEBUG 1520 virtual void Verify() const; 1521#endif 1522 1523 Handle<Map> map() const { return map_; } 1524 1525 DECLARE_CONCRETE_INSTRUCTION(CheckMap, "check_map") 1526 1527 protected: 1528 virtual bool DataEquals(HValue* other) const { 1529 HCheckMap* b = HCheckMap::cast(other); 1530 return map_.is_identical_to(b->map()); 1531 } 1532 1533 private: 1534 Handle<Map> map_; 1535}; 1536 1537 1538class HCheckFunction: public HUnaryOperation { 1539 public: 1540 HCheckFunction(HValue* value, Handle<JSFunction> function) 1541 : HUnaryOperation(value), target_(function) { 1542 set_representation(Representation::Tagged()); 1543 SetFlag(kUseGVN); 1544 } 1545 1546 virtual bool IsCheckInstruction() const { return true; } 1547 1548 virtual Representation RequiredInputRepresentation(int index) const { 1549 return Representation::Tagged(); 1550 } 1551 virtual void PrintDataTo(StringStream* stream) const; 1552 virtual HType CalculateInferredType() const; 1553 1554#ifdef DEBUG 1555 virtual void Verify() const; 1556#endif 1557 1558 Handle<JSFunction> target() const { return target_; } 1559 1560 DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check_function") 1561 1562 protected: 1563 virtual bool DataEquals(HValue* other) const { 1564 HCheckFunction* b = HCheckFunction::cast(other); 1565 return target_.is_identical_to(b->target()); 1566 } 1567 1568 private: 1569 Handle<JSFunction> target_; 1570}; 1571 1572 1573class HCheckInstanceType: public HUnaryOperation { 1574 public: 1575 // Check that the instance type is in the range [first, last] where 1576 // both first and last are included. 1577 HCheckInstanceType(HValue* value, InstanceType first, InstanceType last) 1578 : HUnaryOperation(value), first_(first), last_(last) { 1579 ASSERT(first <= last); 1580 set_representation(Representation::Tagged()); 1581 SetFlag(kUseGVN); 1582 } 1583 1584 virtual bool IsCheckInstruction() const { return true; } 1585 1586 virtual Representation RequiredInputRepresentation(int index) const { 1587 return Representation::Tagged(); 1588 } 1589 1590#ifdef DEBUG 1591 virtual void Verify() const; 1592#endif 1593 1594 static HCheckInstanceType* NewIsJSObjectOrJSFunction(HValue* value); 1595 1596 InstanceType first() const { return first_; } 1597 InstanceType last() const { return last_; } 1598 1599 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check_instance_type") 1600 1601 protected: 1602 // TODO(ager): It could be nice to allow the ommision of instance 1603 // type checks if we have already performed an instance type check 1604 // with a larger range. 1605 virtual bool DataEquals(HValue* other) const { 1606 HCheckInstanceType* b = HCheckInstanceType::cast(other); 1607 return (first_ == b->first()) && (last_ == b->last()); 1608 } 1609 1610 private: 1611 InstanceType first_; 1612 InstanceType last_; 1613}; 1614 1615 1616class HCheckNonSmi: public HUnaryOperation { 1617 public: 1618 explicit HCheckNonSmi(HValue* value) : HUnaryOperation(value) { 1619 set_representation(Representation::Tagged()); 1620 SetFlag(kUseGVN); 1621 } 1622 1623 virtual bool IsCheckInstruction() const { return true; } 1624 1625 virtual Representation RequiredInputRepresentation(int index) const { 1626 return Representation::Tagged(); 1627 } 1628 1629 virtual HType CalculateInferredType() const; 1630 1631#ifdef DEBUG 1632 virtual void Verify() const; 1633#endif 1634 1635 DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check_non_smi") 1636}; 1637 1638 1639class HCheckPrototypeMaps: public HInstruction { 1640 public: 1641 HCheckPrototypeMaps(Handle<JSObject> prototype, Handle<JSObject> holder) 1642 : prototype_(prototype), holder_(holder) { 1643 SetFlag(kUseGVN); 1644 SetFlag(kDependsOnMaps); 1645 } 1646 1647 virtual bool IsCheckInstruction() const { return true; } 1648 1649#ifdef DEBUG 1650 virtual void Verify() const; 1651#endif 1652 1653 Handle<JSObject> prototype() const { return prototype_; } 1654 Handle<JSObject> holder() const { return holder_; } 1655 1656 DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check_prototype_maps") 1657 1658 virtual intptr_t Hashcode() const { 1659 ASSERT(!Heap::IsAllocationAllowed()); 1660 intptr_t hash = reinterpret_cast<intptr_t>(*prototype()); 1661 hash = 17 * hash + reinterpret_cast<intptr_t>(*holder()); 1662 return hash; 1663 } 1664 1665 protected: 1666 virtual bool DataEquals(HValue* other) const { 1667 HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other); 1668 return prototype_.is_identical_to(b->prototype()) && 1669 holder_.is_identical_to(b->holder()); 1670 } 1671 1672 private: 1673 Handle<JSObject> prototype_; 1674 Handle<JSObject> holder_; 1675}; 1676 1677 1678class HCheckSmi: public HUnaryOperation { 1679 public: 1680 explicit HCheckSmi(HValue* value) : HUnaryOperation(value) { 1681 set_representation(Representation::Tagged()); 1682 SetFlag(kUseGVN); 1683 } 1684 1685 virtual bool IsCheckInstruction() const { return true; } 1686 1687 virtual Representation RequiredInputRepresentation(int index) const { 1688 return Representation::Tagged(); 1689 } 1690 virtual HType CalculateInferredType() const; 1691 1692#ifdef DEBUG 1693 virtual void Verify() const; 1694#endif 1695 1696 DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check_smi") 1697}; 1698 1699 1700class HPhi: public HValue { 1701 public: 1702 explicit HPhi(int merged_index) 1703 : inputs_(2), 1704 merged_index_(merged_index), 1705 phi_id_(-1) { 1706 for (int i = 0; i < Representation::kNumRepresentations; i++) { 1707 non_phi_uses_[i] = 0; 1708 indirect_uses_[i] = 0; 1709 } 1710 ASSERT(merged_index >= 0); 1711 set_representation(Representation::Tagged()); 1712 SetFlag(kFlexibleRepresentation); 1713 } 1714 1715 virtual Representation InferredRepresentation() const { 1716 bool double_occurred = false; 1717 bool int32_occurred = false; 1718 for (int i = 0; i < OperandCount(); ++i) { 1719 HValue* value = OperandAt(i); 1720 if (value->representation().IsDouble()) double_occurred = true; 1721 if (value->representation().IsInteger32()) int32_occurred = true; 1722 if (value->representation().IsTagged()) return Representation::Tagged(); 1723 } 1724 1725 if (double_occurred) return Representation::Double(); 1726 if (int32_occurred) return Representation::Integer32(); 1727 return Representation::None(); 1728 } 1729 1730 virtual Range* InferRange(); 1731 virtual Representation RequiredInputRepresentation(int index) const { 1732 return representation(); 1733 } 1734 virtual HType CalculateInferredType() const; 1735 virtual int OperandCount() const { return inputs_.length(); } 1736 virtual HValue* OperandAt(int index) const { return inputs_[index]; } 1737 HValue* GetRedundantReplacement() const; 1738 void AddInput(HValue* value); 1739 1740 bool HasReceiverOperand(); 1741 1742 int merged_index() const { return merged_index_; } 1743 1744 virtual const char* Mnemonic() const { return "phi"; } 1745 1746 virtual void PrintTo(StringStream* stream) const; 1747 1748#ifdef DEBUG 1749 virtual void Verify() const; 1750#endif 1751 1752 DECLARE_INSTRUCTION(Phi) 1753 1754 void InitRealUses(int id); 1755 void AddNonPhiUsesFrom(HPhi* other); 1756 void AddIndirectUsesTo(int* use_count); 1757 1758 int tagged_non_phi_uses() const { 1759 return non_phi_uses_[Representation::kTagged]; 1760 } 1761 int int32_non_phi_uses() const { 1762 return non_phi_uses_[Representation::kInteger32]; 1763 } 1764 int double_non_phi_uses() const { 1765 return non_phi_uses_[Representation::kDouble]; 1766 } 1767 int tagged_indirect_uses() const { 1768 return indirect_uses_[Representation::kTagged]; 1769 } 1770 int int32_indirect_uses() const { 1771 return indirect_uses_[Representation::kInteger32]; 1772 } 1773 int double_indirect_uses() const { 1774 return indirect_uses_[Representation::kDouble]; 1775 } 1776 int phi_id() { return phi_id_; } 1777 1778 protected: 1779 virtual void DeleteFromGraph(); 1780 virtual void InternalSetOperandAt(int index, HValue* value) { 1781 inputs_[index] = value; 1782 } 1783 1784 private: 1785 ZoneList<HValue*> inputs_; 1786 int merged_index_; 1787 1788 int non_phi_uses_[Representation::kNumRepresentations]; 1789 int indirect_uses_[Representation::kNumRepresentations]; 1790 int phi_id_; 1791}; 1792 1793 1794class HArgumentsObject: public HInstruction { 1795 public: 1796 HArgumentsObject() { 1797 set_representation(Representation::Tagged()); 1798 SetFlag(kIsArguments); 1799 } 1800 1801 DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject, "arguments-object") 1802}; 1803 1804 1805class HConstant: public HInstruction { 1806 public: 1807 HConstant(Handle<Object> handle, Representation r); 1808 1809 Handle<Object> handle() const { return handle_; } 1810 1811 bool InOldSpace() const { return !Heap::InNewSpace(*handle_); } 1812 1813 virtual bool EmitAtUses() const { return !representation().IsDouble(); } 1814 virtual void PrintDataTo(StringStream* stream) const; 1815 virtual HType CalculateInferredType() const; 1816 bool IsInteger() const { return handle_->IsSmi(); } 1817 HConstant* CopyToRepresentation(Representation r) const; 1818 HConstant* CopyToTruncatedInt32() const; 1819 bool HasInteger32Value() const { return has_int32_value_; } 1820 int32_t Integer32Value() const { 1821 ASSERT(HasInteger32Value()); 1822 return int32_value_; 1823 } 1824 bool HasDoubleValue() const { return has_double_value_; } 1825 double DoubleValue() const { 1826 ASSERT(HasDoubleValue()); 1827 return double_value_; 1828 } 1829 bool HasStringValue() const { return handle_->IsString(); } 1830 1831 virtual intptr_t Hashcode() const { 1832 ASSERT(!Heap::allow_allocation(false)); 1833 return reinterpret_cast<intptr_t>(*handle()); 1834 } 1835 1836#ifdef DEBUG 1837 virtual void Verify() const { } 1838#endif 1839 1840 DECLARE_CONCRETE_INSTRUCTION(Constant, "constant") 1841 1842 protected: 1843 virtual Range* InferRange(); 1844 1845 virtual bool DataEquals(HValue* other) const { 1846 HConstant* other_constant = HConstant::cast(other); 1847 return handle().is_identical_to(other_constant->handle()); 1848 } 1849 1850 private: 1851 Handle<Object> handle_; 1852 HType constant_type_; 1853 1854 // The following two values represent the int32 and the double value of the 1855 // given constant if there is a lossless conversion between the constant 1856 // and the specific representation. 1857 bool has_int32_value_; 1858 int32_t int32_value_; 1859 bool has_double_value_; 1860 double double_value_; 1861}; 1862 1863 1864class HBinaryOperation: public HInstruction { 1865 public: 1866 HBinaryOperation(HValue* left, HValue* right) { 1867 ASSERT(left != NULL && right != NULL); 1868 SetOperandAt(0, left); 1869 SetOperandAt(1, right); 1870 } 1871 1872 HValue* left() const { return OperandAt(0); } 1873 HValue* right() const { return OperandAt(1); } 1874 1875 // TODO(kasperl): Move these helpers to the IA-32 Lithium 1876 // instruction sequence builder. 1877 HValue* LeastConstantOperand() const { 1878 if (IsCommutative() && left()->IsConstant()) return right(); 1879 return left(); 1880 } 1881 HValue* MostConstantOperand() const { 1882 if (IsCommutative() && left()->IsConstant()) return left(); 1883 return right(); 1884 } 1885 1886 virtual bool IsCommutative() const { return false; } 1887 1888 virtual void PrintDataTo(StringStream* stream) const; 1889 virtual int OperandCount() const { return operands_.length(); } 1890 virtual HValue* OperandAt(int index) const { return operands_[index]; } 1891 1892 DECLARE_INSTRUCTION(BinaryOperation) 1893 1894 protected: 1895 virtual void InternalSetOperandAt(int index, HValue* value) { 1896 operands_[index] = value; 1897 } 1898 1899 private: 1900 HOperandVector<2> operands_; 1901}; 1902 1903 1904class HApplyArguments: public HInstruction { 1905 public: 1906 HApplyArguments(HValue* function, 1907 HValue* receiver, 1908 HValue* length, 1909 HValue* elements) { 1910 set_representation(Representation::Tagged()); 1911 SetOperandAt(0, function); 1912 SetOperandAt(1, receiver); 1913 SetOperandAt(2, length); 1914 SetOperandAt(3, elements); 1915 } 1916 1917 virtual Representation RequiredInputRepresentation(int index) const { 1918 // The length is untagged, all other inputs are tagged. 1919 return (index == 2) 1920 ? Representation::Integer32() 1921 : Representation::Tagged(); 1922 } 1923 1924 HValue* function() const { return OperandAt(0); } 1925 HValue* receiver() const { return OperandAt(1); } 1926 HValue* length() const { return OperandAt(2); } 1927 HValue* elements() const { return OperandAt(3); } 1928 1929 virtual int OperandCount() const { return operands_.length(); } 1930 virtual HValue* OperandAt(int index) const { return operands_[index]; } 1931 1932 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply_arguments") 1933 1934 1935 1936 protected: 1937 virtual void InternalSetOperandAt(int index, HValue* value) { 1938 operands_[index] = value; 1939 } 1940 1941 private: 1942 HOperandVector<4> operands_; 1943}; 1944 1945 1946class HArgumentsElements: public HInstruction { 1947 public: 1948 HArgumentsElements() { 1949 // The value produced by this instruction is a pointer into the stack 1950 // that looks as if it was a smi because of alignment. 1951 set_representation(Representation::Tagged()); 1952 SetFlag(kUseGVN); 1953 } 1954 1955 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments_elements") 1956}; 1957 1958 1959class HArgumentsLength: public HUnaryOperation { 1960 public: 1961 explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) { 1962 set_representation(Representation::Integer32()); 1963 SetFlag(kUseGVN); 1964 } 1965 1966 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments_length") 1967}; 1968 1969 1970class HAccessArgumentsAt: public HInstruction { 1971 public: 1972 HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) { 1973 set_representation(Representation::Tagged()); 1974 SetFlag(kUseGVN); 1975 SetOperandAt(0, arguments); 1976 SetOperandAt(1, length); 1977 SetOperandAt(2, index); 1978 } 1979 1980 virtual void PrintDataTo(StringStream* stream) const; 1981 1982 virtual Representation RequiredInputRepresentation(int index) const { 1983 // The arguments elements is considered tagged. 1984 return index == 0 1985 ? Representation::Tagged() 1986 : Representation::Integer32(); 1987 } 1988 1989 HValue* arguments() const { return operands_[0]; } 1990 HValue* length() const { return operands_[1]; } 1991 HValue* index() const { return operands_[2]; } 1992 1993 virtual int OperandCount() const { return operands_.length(); } 1994 virtual HValue* OperandAt(int index) const { return operands_[index]; } 1995 1996 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access_arguments_at") 1997 1998 protected: 1999 virtual void InternalSetOperandAt(int index, HValue* value) { 2000 operands_[index] = value; 2001 } 2002 2003 private: 2004 HOperandVector<3> operands_; 2005}; 2006 2007 2008class HBoundsCheck: public HBinaryOperation { 2009 public: 2010 HBoundsCheck(HValue* index, HValue* length) 2011 : HBinaryOperation(index, length) { 2012 SetFlag(kUseGVN); 2013 } 2014 2015 virtual bool IsCheckInstruction() const { return true; } 2016 2017 virtual Representation RequiredInputRepresentation(int index) const { 2018 return Representation::Integer32(); 2019 } 2020 2021#ifdef DEBUG 2022 virtual void Verify() const; 2023#endif 2024 2025 HValue* index() const { return left(); } 2026 HValue* length() const { return right(); } 2027 2028 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds_check") 2029}; 2030 2031 2032class HBitwiseBinaryOperation: public HBinaryOperation { 2033 public: 2034 HBitwiseBinaryOperation(HValue* left, HValue* right) 2035 : HBinaryOperation(left, right) { 2036 // Default to truncating, Integer32, UseGVN. 2037 set_representation(Representation::Integer32()); 2038 SetFlag(kTruncatingToInt32); 2039 SetFlag(kUseGVN); 2040 } 2041 2042 virtual Representation RequiredInputRepresentation(int index) const { 2043 return Representation::Integer32(); 2044 } 2045 2046 DECLARE_INSTRUCTION(BitwiseBinaryOperation) 2047}; 2048 2049 2050class HArithmeticBinaryOperation: public HBinaryOperation { 2051 public: 2052 HArithmeticBinaryOperation(HValue* left, HValue* right) 2053 : HBinaryOperation(left, right) { 2054 set_representation(Representation::Tagged()); 2055 SetFlag(kFlexibleRepresentation); 2056 SetFlagMask(AllSideEffects()); 2057 } 2058 2059 virtual void RepresentationChanged(Representation to) { 2060 if (!to.IsTagged()) { 2061 ClearFlagMask(AllSideEffects()); 2062 SetFlag(kUseGVN); 2063 } 2064 } 2065 2066 virtual HType CalculateInferredType() const; 2067 virtual Representation RequiredInputRepresentation(int index) const { 2068 return representation(); 2069 } 2070 virtual Representation InferredRepresentation() const { 2071 if (left()->representation().Equals(right()->representation())) { 2072 return left()->representation(); 2073 } 2074 return HValue::InferredRepresentation(); 2075 } 2076 2077 DECLARE_INSTRUCTION(ArithmeticBinaryOperation) 2078}; 2079 2080 2081class HCompare: public HBinaryOperation { 2082 public: 2083 HCompare(HValue* left, HValue* right, Token::Value token) 2084 : HBinaryOperation(left, right), token_(token) { 2085 ASSERT(Token::IsCompareOp(token)); 2086 set_representation(Representation::Tagged()); 2087 SetFlagMask(AllSideEffects()); 2088 } 2089 2090 void SetInputRepresentation(Representation r); 2091 virtual bool EmitAtUses() const { return uses()->length() <= 1; } 2092 virtual Representation RequiredInputRepresentation(int index) const { 2093 return input_representation_; 2094 } 2095 Representation GetInputRepresentation() const { 2096 return input_representation_; 2097 } 2098 Token::Value token() const { return token_; } 2099 virtual void PrintDataTo(StringStream* stream) const; 2100 2101 virtual HType CalculateInferredType() const; 2102 2103 virtual intptr_t Hashcode() const { 2104 return HValue::Hashcode() * 7 + token_; 2105 } 2106 2107 DECLARE_CONCRETE_INSTRUCTION(Compare, "compare") 2108 2109 protected: 2110 virtual bool DataEquals(HValue* other) const { 2111 HCompare* comp = HCompare::cast(other); 2112 return token_ == comp->token(); 2113 } 2114 2115 private: 2116 Representation input_representation_; 2117 Token::Value token_; 2118}; 2119 2120 2121class HCompareJSObjectEq: public HBinaryOperation { 2122 public: 2123 HCompareJSObjectEq(HValue* left, HValue* right) 2124 : HBinaryOperation(left, right) { 2125 set_representation(Representation::Tagged()); 2126 SetFlag(kUseGVN); 2127 } 2128 2129 virtual bool EmitAtUses() const { return uses()->length() <= 1; } 2130 virtual Representation RequiredInputRepresentation(int index) const { 2131 return Representation::Tagged(); 2132 } 2133 virtual HType CalculateInferredType() const; 2134 2135 DECLARE_CONCRETE_INSTRUCTION(CompareJSObjectEq, "compare-js-object-eq") 2136}; 2137 2138 2139class HUnaryPredicate: public HUnaryOperation { 2140 public: 2141 explicit HUnaryPredicate(HValue* value) : HUnaryOperation(value) { 2142 set_representation(Representation::Tagged()); 2143 SetFlag(kUseGVN); 2144 } 2145 virtual bool EmitAtUses() const { return uses()->length() <= 1; } 2146 virtual Representation RequiredInputRepresentation(int index) const { 2147 return Representation::Tagged(); 2148 } 2149 virtual HType CalculateInferredType() const; 2150}; 2151 2152 2153class HIsNull: public HUnaryPredicate { 2154 public: 2155 HIsNull(HValue* value, bool is_strict) 2156 : HUnaryPredicate(value), is_strict_(is_strict) { } 2157 2158 bool is_strict() const { return is_strict_; } 2159 2160 DECLARE_CONCRETE_INSTRUCTION(IsNull, "is_null") 2161 2162 protected: 2163 virtual bool DataEquals(HValue* other) const { 2164 HIsNull* b = HIsNull::cast(other); 2165 return is_strict_ == b->is_strict(); 2166 } 2167 2168 private: 2169 bool is_strict_; 2170}; 2171 2172 2173class HIsObject: public HUnaryPredicate { 2174 public: 2175 explicit HIsObject(HValue* value) : HUnaryPredicate(value) { } 2176 2177 DECLARE_CONCRETE_INSTRUCTION(IsObject, "is_object") 2178}; 2179 2180 2181class HIsSmi: public HUnaryPredicate { 2182 public: 2183 explicit HIsSmi(HValue* value) : HUnaryPredicate(value) { } 2184 2185 DECLARE_CONCRETE_INSTRUCTION(IsSmi, "is_smi") 2186}; 2187 2188 2189class HHasInstanceType: public HUnaryPredicate { 2190 public: 2191 HHasInstanceType(HValue* value, InstanceType type) 2192 : HUnaryPredicate(value), from_(type), to_(type) { } 2193 HHasInstanceType(HValue* value, InstanceType from, InstanceType to) 2194 : HUnaryPredicate(value), from_(from), to_(to) { 2195 ASSERT(to == LAST_TYPE); // Others not implemented yet in backend. 2196 } 2197 2198 InstanceType from() { return from_; } 2199 InstanceType to() { return to_; } 2200 2201 virtual void PrintDataTo(StringStream* stream) const; 2202 2203 DECLARE_CONCRETE_INSTRUCTION(HasInstanceType, "has_instance_type") 2204 2205 protected: 2206 virtual bool DataEquals(HValue* other) const { 2207 HHasInstanceType* b = HHasInstanceType::cast(other); 2208 return (from_ == b->from()) && (to_ == b->to()); 2209 } 2210 2211 private: 2212 InstanceType from_; 2213 InstanceType to_; // Inclusive range, not all combinations work. 2214}; 2215 2216 2217class HHasCachedArrayIndex: public HUnaryPredicate { 2218 public: 2219 explicit HHasCachedArrayIndex(HValue* value) : HUnaryPredicate(value) { } 2220 2221 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndex, "has_cached_array_index") 2222}; 2223 2224 2225class HClassOfTest: public HUnaryPredicate { 2226 public: 2227 HClassOfTest(HValue* value, Handle<String> class_name) 2228 : HUnaryPredicate(value), class_name_(class_name) { } 2229 2230 DECLARE_CONCRETE_INSTRUCTION(ClassOfTest, "class_of_test") 2231 2232 virtual void PrintDataTo(StringStream* stream) const; 2233 2234 Handle<String> class_name() const { return class_name_; } 2235 2236 protected: 2237 virtual bool DataEquals(HValue* other) const { 2238 HClassOfTest* b = HClassOfTest::cast(other); 2239 return class_name_.is_identical_to(b->class_name_); 2240 } 2241 2242 private: 2243 Handle<String> class_name_; 2244}; 2245 2246 2247class HTypeofIs: public HUnaryPredicate { 2248 public: 2249 HTypeofIs(HValue* value, Handle<String> type_literal) 2250 : HUnaryPredicate(value), type_literal_(type_literal) { } 2251 2252 Handle<String> type_literal() { return type_literal_; } 2253 virtual void PrintDataTo(StringStream* stream) const; 2254 2255 DECLARE_CONCRETE_INSTRUCTION(TypeofIs, "typeof_is") 2256 2257 protected: 2258 virtual bool DataEquals(HValue* other) const { 2259 HTypeofIs* b = HTypeofIs::cast(other); 2260 return type_literal_.is_identical_to(b->type_literal_); 2261 } 2262 2263 private: 2264 Handle<String> type_literal_; 2265}; 2266 2267 2268class HInstanceOf: public HBinaryOperation { 2269 public: 2270 HInstanceOf(HValue* left, HValue* right) : HBinaryOperation(left, right) { 2271 set_representation(Representation::Tagged()); 2272 SetFlagMask(AllSideEffects()); 2273 } 2274 2275 virtual bool EmitAtUses() const { return uses()->length() <= 1; } 2276 2277 virtual Representation RequiredInputRepresentation(int index) const { 2278 return Representation::Tagged(); 2279 } 2280 2281 DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance_of") 2282}; 2283 2284 2285class HInstanceOfKnownGlobal: public HUnaryOperation { 2286 public: 2287 HInstanceOfKnownGlobal(HValue* left, Handle<JSFunction> right) 2288 : HUnaryOperation(left), function_(right) { 2289 set_representation(Representation::Tagged()); 2290 SetFlagMask(AllSideEffects()); 2291 } 2292 2293 Handle<JSFunction> function() { return function_; } 2294 2295 virtual Representation RequiredInputRepresentation(int index) const { 2296 return Representation::Tagged(); 2297 } 2298 2299 DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal, 2300 "instance_of_known_global") 2301 2302 private: 2303 Handle<JSFunction> function_; 2304}; 2305 2306 2307class HPower: public HBinaryOperation { 2308 public: 2309 HPower(HValue* left, HValue* right) 2310 : HBinaryOperation(left, right) { 2311 set_representation(Representation::Double()); 2312 SetFlag(kUseGVN); 2313 } 2314 2315 virtual Representation RequiredInputRepresentation(int index) const { 2316 return (index == 1) ? Representation::None() : Representation::Double(); 2317 } 2318 2319 DECLARE_CONCRETE_INSTRUCTION(Power, "power") 2320}; 2321 2322 2323class HAdd: public HArithmeticBinaryOperation { 2324 public: 2325 HAdd(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) { 2326 SetFlag(kCanOverflow); 2327 } 2328 2329 // Add is only commutative if two integer values are added and not if two 2330 // tagged values are added (because it might be a String concatenation). 2331 virtual bool IsCommutative() const { 2332 return !representation().IsTagged(); 2333 } 2334 2335 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); 2336 2337 virtual HType CalculateInferredType() const; 2338 2339 DECLARE_CONCRETE_INSTRUCTION(Add, "add") 2340 2341 protected: 2342 virtual Range* InferRange(); 2343}; 2344 2345 2346class HSub: public HArithmeticBinaryOperation { 2347 public: 2348 HSub(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) { 2349 SetFlag(kCanOverflow); 2350 } 2351 2352 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); 2353 2354 DECLARE_CONCRETE_INSTRUCTION(Sub, "sub") 2355 2356 protected: 2357 virtual Range* InferRange(); 2358}; 2359 2360 2361class HMul: public HArithmeticBinaryOperation { 2362 public: 2363 HMul(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) { 2364 SetFlag(kCanOverflow); 2365 } 2366 2367 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); 2368 2369 // Only commutative if it is certain that not two objects are multiplicated. 2370 virtual bool IsCommutative() const { 2371 return !representation().IsTagged(); 2372 } 2373 2374 DECLARE_CONCRETE_INSTRUCTION(Mul, "mul") 2375 2376 protected: 2377 virtual Range* InferRange(); 2378}; 2379 2380 2381class HMod: public HArithmeticBinaryOperation { 2382 public: 2383 HMod(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) { 2384 SetFlag(kCanBeDivByZero); 2385 } 2386 2387 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); 2388 2389 DECLARE_CONCRETE_INSTRUCTION(Mod, "mod") 2390 2391 protected: 2392 virtual Range* InferRange(); 2393}; 2394 2395 2396class HDiv: public HArithmeticBinaryOperation { 2397 public: 2398 HDiv(HValue* left, HValue* right) : HArithmeticBinaryOperation(left, right) { 2399 SetFlag(kCanBeDivByZero); 2400 SetFlag(kCanOverflow); 2401 } 2402 2403 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); 2404 2405 DECLARE_CONCRETE_INSTRUCTION(Div, "div") 2406 2407 protected: 2408 virtual Range* InferRange(); 2409}; 2410 2411 2412class HBitAnd: public HBitwiseBinaryOperation { 2413 public: 2414 HBitAnd(HValue* left, HValue* right) 2415 : HBitwiseBinaryOperation(left, right) { } 2416 2417 virtual bool IsCommutative() const { return true; } 2418 virtual HType CalculateInferredType() const; 2419 2420 DECLARE_CONCRETE_INSTRUCTION(BitAnd, "bit_and") 2421 2422 protected: 2423 virtual Range* InferRange(); 2424}; 2425 2426 2427class HBitXor: public HBitwiseBinaryOperation { 2428 public: 2429 HBitXor(HValue* left, HValue* right) 2430 : HBitwiseBinaryOperation(left, right) { } 2431 2432 virtual bool IsCommutative() const { return true; } 2433 virtual HType CalculateInferredType() const; 2434 2435 DECLARE_CONCRETE_INSTRUCTION(BitXor, "bit_xor") 2436}; 2437 2438 2439class HBitOr: public HBitwiseBinaryOperation { 2440 public: 2441 HBitOr(HValue* left, HValue* right) 2442 : HBitwiseBinaryOperation(left, right) { } 2443 2444 virtual bool IsCommutative() const { return true; } 2445 virtual HType CalculateInferredType() const; 2446 2447 DECLARE_CONCRETE_INSTRUCTION(BitOr, "bit_or") 2448 2449 protected: 2450 virtual Range* InferRange(); 2451}; 2452 2453 2454class HShl: public HBitwiseBinaryOperation { 2455 public: 2456 HShl(HValue* left, HValue* right) 2457 : HBitwiseBinaryOperation(left, right) { } 2458 2459 virtual Range* InferRange(); 2460 virtual HType CalculateInferredType() const; 2461 2462 DECLARE_CONCRETE_INSTRUCTION(Shl, "shl") 2463}; 2464 2465 2466class HShr: public HBitwiseBinaryOperation { 2467 public: 2468 HShr(HValue* left, HValue* right) 2469 : HBitwiseBinaryOperation(left, right) { } 2470 2471 virtual HType CalculateInferredType() const; 2472 2473 DECLARE_CONCRETE_INSTRUCTION(Shr, "shr") 2474}; 2475 2476 2477class HSar: public HBitwiseBinaryOperation { 2478 public: 2479 HSar(HValue* left, HValue* right) 2480 : HBitwiseBinaryOperation(left, right) { } 2481 2482 virtual Range* InferRange(); 2483 virtual HType CalculateInferredType() const; 2484 2485 DECLARE_CONCRETE_INSTRUCTION(Sar, "sar") 2486}; 2487 2488 2489class HOsrEntry: public HInstruction { 2490 public: 2491 explicit HOsrEntry(int ast_id) : ast_id_(ast_id) { 2492 SetFlag(kChangesOsrEntries); 2493 } 2494 2495 int ast_id() const { return ast_id_; } 2496 2497 DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr_entry") 2498 2499 private: 2500 int ast_id_; 2501}; 2502 2503 2504class HParameter: public HInstruction { 2505 public: 2506 explicit HParameter(unsigned index) : index_(index) { 2507 set_representation(Representation::Tagged()); 2508 } 2509 2510 unsigned index() const { return index_; } 2511 2512 virtual void PrintDataTo(StringStream* stream) const; 2513 2514 DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter") 2515 2516 private: 2517 unsigned index_; 2518}; 2519 2520 2521class HCallStub: public HInstruction { 2522 public: 2523 HCallStub(CodeStub::Major major_key, int argument_count) 2524 : major_key_(major_key), 2525 argument_count_(argument_count), 2526 transcendental_type_(TranscendentalCache::kNumberOfCaches) { 2527 set_representation(Representation::Tagged()); 2528 SetFlagMask(AllSideEffects()); 2529 } 2530 2531 CodeStub::Major major_key() { return major_key_; } 2532 int argument_count() { return argument_count_; } 2533 2534 void set_transcendental_type(TranscendentalCache::Type transcendental_type) { 2535 transcendental_type_ = transcendental_type; 2536 } 2537 TranscendentalCache::Type transcendental_type() { 2538 return transcendental_type_; 2539 } 2540 virtual void PrintDataTo(StringStream* stream) const; 2541 2542 DECLARE_CONCRETE_INSTRUCTION(CallStub, "call_stub") 2543 2544 private: 2545 CodeStub::Major major_key_; 2546 int argument_count_; 2547 TranscendentalCache::Type transcendental_type_; 2548}; 2549 2550 2551class HUnknownOSRValue: public HInstruction { 2552 public: 2553 HUnknownOSRValue() { set_representation(Representation::Tagged()); } 2554 2555 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown_osr_value") 2556}; 2557 2558 2559class HLoadGlobal: public HInstruction { 2560 public: 2561 HLoadGlobal(Handle<JSGlobalPropertyCell> cell, bool check_hole_value) 2562 : cell_(cell), check_hole_value_(check_hole_value) { 2563 set_representation(Representation::Tagged()); 2564 SetFlag(kUseGVN); 2565 SetFlag(kDependsOnGlobalVars); 2566 } 2567 2568 Handle<JSGlobalPropertyCell> cell() const { return cell_; } 2569 bool check_hole_value() const { return check_hole_value_; } 2570 2571 virtual Representation RequiredInputRepresentation(int index) const { 2572 return Representation::Tagged(); 2573 } 2574 virtual void PrintDataTo(StringStream* stream) const; 2575 2576 virtual intptr_t Hashcode() const { 2577 ASSERT(!Heap::allow_allocation(false)); 2578 return reinterpret_cast<intptr_t>(*cell_); 2579 } 2580 2581 DECLARE_CONCRETE_INSTRUCTION(LoadGlobal, "load_global") 2582 2583 protected: 2584 virtual bool DataEquals(HValue* other) const { 2585 HLoadGlobal* b = HLoadGlobal::cast(other); 2586 return cell_.is_identical_to(b->cell()); 2587 } 2588 2589 private: 2590 Handle<JSGlobalPropertyCell> cell_; 2591 bool check_hole_value_; 2592}; 2593 2594 2595class HStoreGlobal: public HUnaryOperation { 2596 public: 2597 HStoreGlobal(HValue* value, Handle<JSGlobalPropertyCell> cell) 2598 : HUnaryOperation(value), cell_(cell) { 2599 SetFlag(kChangesGlobalVars); 2600 } 2601 2602 Handle<JSGlobalPropertyCell> cell() const { return cell_; } 2603 2604 virtual Representation RequiredInputRepresentation(int index) const { 2605 return Representation::Tagged(); 2606 } 2607 virtual void PrintDataTo(StringStream* stream) const; 2608 2609 DECLARE_CONCRETE_INSTRUCTION(StoreGlobal, "store_global") 2610 2611 protected: 2612 virtual bool DataEquals(HValue* other) const { 2613 HStoreGlobal* b = HStoreGlobal::cast(other); 2614 return cell_.is_identical_to(b->cell()); 2615 } 2616 2617 private: 2618 Handle<JSGlobalPropertyCell> cell_; 2619}; 2620 2621 2622class HLoadContextSlot: public HInstruction { 2623 public: 2624 HLoadContextSlot(int context_chain_length , int slot_index) 2625 : context_chain_length_(context_chain_length), slot_index_(slot_index) { 2626 set_representation(Representation::Tagged()); 2627 SetFlag(kUseGVN); 2628 SetFlag(kDependsOnCalls); 2629 } 2630 2631 int context_chain_length() const { return context_chain_length_; } 2632 int slot_index() const { return slot_index_; } 2633 2634 virtual void PrintDataTo(StringStream* stream) const; 2635 2636 virtual intptr_t Hashcode() const { 2637 return context_chain_length() * 29 + slot_index(); 2638 } 2639 2640 DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load_context_slot") 2641 2642 protected: 2643 virtual bool DataEquals(HValue* other) const { 2644 HLoadContextSlot* b = HLoadContextSlot::cast(other); 2645 return (context_chain_length() == b->context_chain_length()) 2646 && (slot_index() == b->slot_index()); 2647 } 2648 2649 private: 2650 int context_chain_length_; 2651 int slot_index_; 2652}; 2653 2654 2655class HLoadNamedField: public HUnaryOperation { 2656 public: 2657 HLoadNamedField(HValue* object, bool is_in_object, int offset) 2658 : HUnaryOperation(object), 2659 is_in_object_(is_in_object), 2660 offset_(offset) { 2661 set_representation(Representation::Tagged()); 2662 SetFlag(kUseGVN); 2663 if (is_in_object) { 2664 SetFlag(kDependsOnInobjectFields); 2665 } else { 2666 SetFlag(kDependsOnBackingStoreFields); 2667 } 2668 } 2669 2670 HValue* object() const { return OperandAt(0); } 2671 bool is_in_object() const { return is_in_object_; } 2672 int offset() const { return offset_; } 2673 2674 virtual Representation RequiredInputRepresentation(int index) const { 2675 return Representation::Tagged(); 2676 } 2677 virtual void PrintDataTo(StringStream* stream) const; 2678 2679 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load_named_field") 2680 2681 protected: 2682 virtual bool DataEquals(HValue* other) const { 2683 HLoadNamedField* b = HLoadNamedField::cast(other); 2684 return is_in_object_ == b->is_in_object_ && offset_ == b->offset_; 2685 } 2686 2687 private: 2688 bool is_in_object_; 2689 int offset_; 2690}; 2691 2692 2693class HLoadNamedGeneric: public HUnaryOperation { 2694 public: 2695 HLoadNamedGeneric(HValue* object, Handle<Object> name) 2696 : HUnaryOperation(object), name_(name) { 2697 set_representation(Representation::Tagged()); 2698 SetFlagMask(AllSideEffects()); 2699 } 2700 2701 HValue* object() const { return OperandAt(0); } 2702 Handle<Object> name() const { return name_; } 2703 2704 virtual Representation RequiredInputRepresentation(int index) const { 2705 return Representation::Tagged(); 2706 } 2707 2708 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load_named_generic") 2709 2710 protected: 2711 virtual bool DataEquals(HValue* other) const { 2712 HLoadNamedGeneric* b = HLoadNamedGeneric::cast(other); 2713 return name_.is_identical_to(b->name_); 2714 } 2715 2716 private: 2717 Handle<Object> name_; 2718}; 2719 2720 2721class HLoadFunctionPrototype: public HUnaryOperation { 2722 public: 2723 explicit HLoadFunctionPrototype(HValue* function) 2724 : HUnaryOperation(function) { 2725 set_representation(Representation::Tagged()); 2726 SetFlagMask(kDependsOnFunctionPrototypes); 2727 } 2728 2729 HValue* function() const { return OperandAt(0); } 2730 2731 virtual Representation RequiredInputRepresentation(int index) const { 2732 return Representation::Tagged(); 2733 } 2734 2735 DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load_function_prototype") 2736 2737 protected: 2738 virtual bool DataEquals(HValue* other) const { return true; } 2739}; 2740 2741 2742class HLoadKeyed: public HBinaryOperation { 2743 public: 2744 HLoadKeyed(HValue* obj, HValue* key) : HBinaryOperation(obj, key) { 2745 set_representation(Representation::Tagged()); 2746 } 2747 2748 virtual void PrintDataTo(StringStream* stream) const; 2749 2750 virtual Representation RequiredInputRepresentation(int index) const { 2751 return Representation::Tagged(); 2752 } 2753 HValue* object() const { return OperandAt(0); } 2754 HValue* key() const { return OperandAt(1); } 2755 2756 DECLARE_INSTRUCTION(LoadKeyed) 2757}; 2758 2759 2760class HLoadKeyedFastElement: public HLoadKeyed { 2761 public: 2762 HLoadKeyedFastElement(HValue* obj, HValue* key) : HLoadKeyed(obj, key) { 2763 SetFlag(kDependsOnArrayElements); 2764 SetFlag(kUseGVN); 2765 } 2766 2767 virtual Representation RequiredInputRepresentation(int index) const { 2768 // The key is supposed to be Integer32. 2769 return (index == 1) ? Representation::Integer32() 2770 : Representation::Tagged(); 2771 } 2772 2773 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement, 2774 "load_keyed_fast_element") 2775}; 2776 2777 2778class HLoadKeyedGeneric: public HLoadKeyed { 2779 public: 2780 HLoadKeyedGeneric(HValue* obj, HValue* key) : HLoadKeyed(obj, key) { 2781 SetFlagMask(AllSideEffects()); 2782 } 2783 2784 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load_keyed_generic") 2785}; 2786 2787 2788static inline bool StoringValueNeedsWriteBarrier(HValue* value) { 2789 return !value->type().IsSmi() && 2790 !(value->IsConstant() && HConstant::cast(value)->InOldSpace()); 2791} 2792 2793 2794class HStoreNamed: public HBinaryOperation { 2795 public: 2796 HStoreNamed(HValue* obj, Handle<Object> name, HValue* val) 2797 : HBinaryOperation(obj, val), name_(name) { 2798 } 2799 2800 virtual Representation RequiredInputRepresentation(int index) const { 2801 return Representation::Tagged(); 2802 } 2803 2804 virtual void PrintDataTo(StringStream* stream) const; 2805 2806 HValue* object() const { return OperandAt(0); } 2807 Handle<Object> name() const { return name_; } 2808 HValue* value() const { return OperandAt(1); } 2809 void set_value(HValue* value) { SetOperandAt(1, value); } 2810 2811 bool NeedsWriteBarrier() const { 2812 return StoringValueNeedsWriteBarrier(value()); 2813 } 2814 2815 DECLARE_INSTRUCTION(StoreNamed) 2816 2817 protected: 2818 virtual bool DataEquals(HValue* other) const { 2819 HStoreNamed* b = HStoreNamed::cast(other); 2820 return name_.is_identical_to(b->name_); 2821 } 2822 2823 private: 2824 Handle<Object> name_; 2825}; 2826 2827 2828class HStoreNamedField: public HStoreNamed { 2829 public: 2830 HStoreNamedField(HValue* obj, 2831 Handle<Object> name, 2832 HValue* val, 2833 bool in_object, 2834 int offset) 2835 : HStoreNamed(obj, name, val), 2836 is_in_object_(in_object), 2837 offset_(offset) { 2838 if (is_in_object_) { 2839 SetFlag(kChangesInobjectFields); 2840 } else { 2841 SetFlag(kChangesBackingStoreFields); 2842 } 2843 } 2844 2845 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store_named_field") 2846 2847 virtual Representation RequiredInputRepresentation(int index) const { 2848 return Representation::Tagged(); 2849 } 2850 virtual void PrintDataTo(StringStream* stream) const; 2851 2852 bool is_in_object() const { return is_in_object_; } 2853 int offset() const { return offset_; } 2854 Handle<Map> transition() const { return transition_; } 2855 void set_transition(Handle<Map> map) { transition_ = map; } 2856 2857 private: 2858 bool is_in_object_; 2859 int offset_; 2860 Handle<Map> transition_; 2861}; 2862 2863 2864class HStoreNamedGeneric: public HStoreNamed { 2865 public: 2866 HStoreNamedGeneric(HValue* obj, Handle<Object> name, HValue* val) 2867 : HStoreNamed(obj, name, val) { 2868 SetFlagMask(AllSideEffects()); 2869 } 2870 2871 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store_named_generic") 2872}; 2873 2874 2875class HStoreKeyed: public HInstruction { 2876 public: 2877 HStoreKeyed(HValue* obj, HValue* key, HValue* val) { 2878 SetOperandAt(0, obj); 2879 SetOperandAt(1, key); 2880 SetOperandAt(2, val); 2881 } 2882 2883 virtual void PrintDataTo(StringStream* stream) const; 2884 virtual int OperandCount() const { return operands_.length(); } 2885 virtual HValue* OperandAt(int index) const { return operands_[index]; } 2886 2887 virtual Representation RequiredInputRepresentation(int index) const { 2888 return Representation::Tagged(); 2889 } 2890 2891 HValue* object() const { return OperandAt(0); } 2892 HValue* key() const { return OperandAt(1); } 2893 HValue* value() const { return OperandAt(2); } 2894 2895 bool NeedsWriteBarrier() const { 2896 return StoringValueNeedsWriteBarrier(value()); 2897 } 2898 2899 DECLARE_INSTRUCTION(StoreKeyed) 2900 2901 protected: 2902 virtual void InternalSetOperandAt(int index, HValue* value) { 2903 operands_[index] = value; 2904 } 2905 2906 private: 2907 HOperandVector<3> operands_; 2908}; 2909 2910 2911class HStoreKeyedFastElement: public HStoreKeyed { 2912 public: 2913 HStoreKeyedFastElement(HValue* obj, HValue* key, HValue* val) 2914 : HStoreKeyed(obj, key, val) { 2915 SetFlag(kChangesArrayElements); 2916 } 2917 2918 virtual Representation RequiredInputRepresentation(int index) const { 2919 // The key is supposed to be Integer32. 2920 return (index == 1) ? Representation::Integer32() 2921 : Representation::Tagged(); 2922 } 2923 2924 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastElement, 2925 "store_keyed_fast_element") 2926}; 2927 2928 2929class HStoreKeyedGeneric: public HStoreKeyed { 2930 public: 2931 HStoreKeyedGeneric(HValue* obj, HValue* key, HValue* val) 2932 : HStoreKeyed(obj, key, val) { 2933 SetFlagMask(AllSideEffects()); 2934 } 2935 2936 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store_keyed_generic") 2937}; 2938 2939 2940class HMaterializedLiteral: public HInstruction { 2941 public: 2942 HMaterializedLiteral(int index, int depth) 2943 : literal_index_(index), depth_(depth) { 2944 set_representation(Representation::Tagged()); 2945 } 2946 2947 int literal_index() const { return literal_index_; } 2948 int depth() const { return depth_; } 2949 2950 DECLARE_INSTRUCTION(MaterializedLiteral) 2951 2952 private: 2953 int literal_index_; 2954 int depth_; 2955}; 2956 2957 2958class HArrayLiteral: public HMaterializedLiteral { 2959 public: 2960 HArrayLiteral(Handle<FixedArray> constant_elements, 2961 int length, 2962 int literal_index, 2963 int depth) 2964 : HMaterializedLiteral(literal_index, depth), 2965 length_(length), 2966 constant_elements_(constant_elements) {} 2967 2968 Handle<FixedArray> constant_elements() const { return constant_elements_; } 2969 int length() const { return length_; } 2970 2971 bool IsCopyOnWrite() const; 2972 2973 DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral, "array_literal") 2974 2975 private: 2976 int length_; 2977 Handle<FixedArray> constant_elements_; 2978}; 2979 2980 2981class HObjectLiteral: public HMaterializedLiteral { 2982 public: 2983 HObjectLiteral(Handle<FixedArray> constant_properties, 2984 bool fast_elements, 2985 int literal_index, 2986 int depth) 2987 : HMaterializedLiteral(literal_index, depth), 2988 constant_properties_(constant_properties), 2989 fast_elements_(fast_elements) {} 2990 2991 Handle<FixedArray> constant_properties() const { 2992 return constant_properties_; 2993 } 2994 bool fast_elements() const { return fast_elements_; } 2995 2996 DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral, "object_literal") 2997 2998 private: 2999 Handle<FixedArray> constant_properties_; 3000 bool fast_elements_; 3001}; 3002 3003 3004class HRegExpLiteral: public HMaterializedLiteral { 3005 public: 3006 HRegExpLiteral(Handle<String> pattern, 3007 Handle<String> flags, 3008 int literal_index) 3009 : HMaterializedLiteral(literal_index, 0), 3010 pattern_(pattern), 3011 flags_(flags) { } 3012 3013 Handle<String> pattern() { return pattern_; } 3014 Handle<String> flags() { return flags_; } 3015 3016 DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp_literal") 3017 3018 private: 3019 Handle<String> pattern_; 3020 Handle<String> flags_; 3021}; 3022 3023 3024class HFunctionLiteral: public HInstruction { 3025 public: 3026 HFunctionLiteral(Handle<SharedFunctionInfo> shared, bool pretenure) 3027 : shared_info_(shared), pretenure_(pretenure) { 3028 set_representation(Representation::Tagged()); 3029 } 3030 3031 DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function_literal") 3032 3033 Handle<SharedFunctionInfo> shared_info() const { return shared_info_; } 3034 bool pretenure() const { return pretenure_; } 3035 3036 private: 3037 Handle<SharedFunctionInfo> shared_info_; 3038 bool pretenure_; 3039}; 3040 3041 3042class HTypeof: public HUnaryOperation { 3043 public: 3044 explicit HTypeof(HValue* value) : HUnaryOperation(value) { 3045 set_representation(Representation::Tagged()); 3046 } 3047 3048 DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof") 3049}; 3050 3051 3052class HValueOf: public HUnaryOperation { 3053 public: 3054 explicit HValueOf(HValue* value) : HUnaryOperation(value) { 3055 set_representation(Representation::Tagged()); 3056 } 3057 3058 DECLARE_CONCRETE_INSTRUCTION(ValueOf, "value_of") 3059}; 3060 3061 3062class HDeleteProperty: public HBinaryOperation { 3063 public: 3064 HDeleteProperty(HValue* obj, HValue* key) 3065 : HBinaryOperation(obj, key) { 3066 set_representation(Representation::Tagged()); 3067 SetFlagMask(AllSideEffects()); 3068 } 3069 3070 virtual Representation RequiredInputRepresentation(int index) const { 3071 return Representation::Tagged(); 3072 } 3073 3074 DECLARE_CONCRETE_INSTRUCTION(DeleteProperty, "delete_property") 3075 3076 HValue* object() const { return left(); } 3077 HValue* key() const { return right(); } 3078}; 3079 3080#undef DECLARE_INSTRUCTION 3081#undef DECLARE_CONCRETE_INSTRUCTION 3082 3083} } // namespace v8::internal 3084 3085#endif // V8_HYDROGEN_INSTRUCTIONS_H_ 3086