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

Unified Diff: src/hydrogen-instructions.h

Issue 1405363003: Move Hydrogen and Lithium to src/crankshaft/ (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebased Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/hydrogen-infer-types.cc ('k') | src/hydrogen-instructions.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/hydrogen-instructions.h
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
deleted file mode 100644
index f7acbb5292c804eb19f47f10a58d99e723e54803..0000000000000000000000000000000000000000
--- a/src/hydrogen-instructions.h
+++ /dev/null
@@ -1,7982 +0,0 @@
-// Copyright 2012 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_HYDROGEN_INSTRUCTIONS_H_
-#define V8_HYDROGEN_INSTRUCTIONS_H_
-
-#include <cstring>
-#include <iosfwd>
-
-#include "src/allocation.h"
-#include "src/base/bits.h"
-#include "src/bit-vector.h"
-#include "src/code-stubs.h"
-#include "src/conversions.h"
-#include "src/deoptimizer.h"
-#include "src/hydrogen-types.h"
-#include "src/small-pointer-list.h"
-#include "src/unique.h"
-#include "src/utils.h"
-#include "src/zone.h"
-
-namespace v8 {
-namespace internal {
-
-// Forward declarations.
-struct ChangesOf;
-class HBasicBlock;
-class HDiv;
-class HEnvironment;
-class HInferRepresentationPhase;
-class HInstruction;
-class HLoopInformation;
-class HStoreNamedField;
-class HValue;
-class LInstruction;
-class LChunkBuilder;
-
-#define HYDROGEN_ABSTRACT_INSTRUCTION_LIST(V) \
- V(ArithmeticBinaryOperation) \
- V(BinaryOperation) \
- V(BitwiseBinaryOperation) \
- V(ControlInstruction) \
- V(Instruction)
-
-
-#define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
- V(AbnormalExit) \
- V(AccessArgumentsAt) \
- V(Add) \
- V(AllocateBlockContext) \
- V(Allocate) \
- V(ApplyArguments) \
- V(ArgumentsElements) \
- V(ArgumentsLength) \
- V(ArgumentsObject) \
- V(Bitwise) \
- V(BlockEntry) \
- V(BoundsCheck) \
- V(BoundsCheckBaseIndexInformation) \
- V(Branch) \
- V(CallWithDescriptor) \
- V(CallJSFunction) \
- V(CallFunction) \
- V(CallNew) \
- V(CallNewArray) \
- V(CallRuntime) \
- V(CallStub) \
- V(CapturedObject) \
- V(Change) \
- V(CheckArrayBufferNotNeutered) \
- V(CheckHeapObject) \
- V(CheckInstanceType) \
- V(CheckMaps) \
- V(CheckMapValue) \
- V(CheckSmi) \
- V(CheckValue) \
- V(ClampToUint8) \
- V(ClassOfTestAndBranch) \
- V(CompareNumericAndBranch) \
- V(CompareHoleAndBranch) \
- V(CompareGeneric) \
- V(CompareMinusZeroAndBranch) \
- V(CompareObjectEqAndBranch) \
- V(CompareMap) \
- V(Constant) \
- V(ConstructDouble) \
- V(Context) \
- V(DateField) \
- V(DebugBreak) \
- V(DeclareGlobals) \
- V(Deoptimize) \
- V(Div) \
- V(DoubleBits) \
- V(DummyUse) \
- V(EnterInlined) \
- V(EnvironmentMarker) \
- V(ForceRepresentation) \
- V(ForInCacheArray) \
- V(ForInPrepareMap) \
- V(GetCachedArrayIndex) \
- V(Goto) \
- V(HasCachedArrayIndexAndBranch) \
- V(HasInstanceTypeAndBranch) \
- V(InnerAllocatedObject) \
- V(InstanceOf) \
- V(InvokeFunction) \
- V(IsConstructCallAndBranch) \
- V(HasInPrototypeChainAndBranch) \
- V(IsStringAndBranch) \
- V(IsSmiAndBranch) \
- V(IsUndetectableAndBranch) \
- V(LeaveInlined) \
- V(LoadContextSlot) \
- V(LoadFieldByIndex) \
- V(LoadFunctionPrototype) \
- V(LoadGlobalGeneric) \
- V(LoadGlobalViaContext) \
- V(LoadKeyed) \
- V(LoadKeyedGeneric) \
- V(LoadNamedField) \
- V(LoadNamedGeneric) \
- V(LoadRoot) \
- V(MapEnumLength) \
- V(MathFloorOfDiv) \
- V(MathMinMax) \
- V(MaybeGrowElements) \
- V(Mod) \
- V(Mul) \
- V(OsrEntry) \
- V(Parameter) \
- V(Power) \
- V(Prologue) \
- V(PushArguments) \
- V(RegExpLiteral) \
- V(Return) \
- V(Ror) \
- V(Sar) \
- V(SeqStringGetChar) \
- V(SeqStringSetChar) \
- V(Shl) \
- V(Shr) \
- V(Simulate) \
- V(StackCheck) \
- V(StoreCodeEntry) \
- V(StoreContextSlot) \
- V(StoreFrameContext) \
- V(StoreGlobalViaContext) \
- V(StoreKeyed) \
- V(StoreKeyedGeneric) \
- V(StoreNamedField) \
- V(StoreNamedGeneric) \
- V(StringAdd) \
- V(StringCharCodeAt) \
- V(StringCharFromCode) \
- V(StringCompareAndBranch) \
- V(Sub) \
- V(ThisFunction) \
- V(ToFastProperties) \
- V(TransitionElementsKind) \
- V(TrapAllocationMemento) \
- V(Typeof) \
- V(TypeofIsAndBranch) \
- V(UnaryMathOperation) \
- V(UnknownOSRValue) \
- V(UseConst) \
- V(WrapReceiver)
-
-#define GVN_TRACKED_FLAG_LIST(V) \
- V(NewSpacePromotion)
-
-#define GVN_UNTRACKED_FLAG_LIST(V) \
- V(ArrayElements) \
- V(ArrayLengths) \
- V(StringLengths) \
- V(BackingStoreFields) \
- V(Calls) \
- V(ContextSlots) \
- V(DoubleArrayElements) \
- V(DoubleFields) \
- V(ElementsKind) \
- V(ElementsPointer) \
- V(GlobalVars) \
- V(InobjectFields) \
- V(Maps) \
- V(OsrEntries) \
- V(ExternalMemory) \
- V(StringChars) \
- V(TypedArrayElements)
-
-
-#define DECLARE_ABSTRACT_INSTRUCTION(type) \
- bool Is##type() const final { return true; } \
- static H##type* cast(HValue* value) { \
- DCHECK(value->Is##type()); \
- return reinterpret_cast<H##type*>(value); \
- }
-
-
-#define DECLARE_CONCRETE_INSTRUCTION(type) \
- LInstruction* CompileToLithium(LChunkBuilder* builder) final; \
- static H##type* cast(HValue* value) { \
- DCHECK(value->Is##type()); \
- return reinterpret_cast<H##type*>(value); \
- } \
- Opcode opcode() const final { return HValue::k##type; }
-
-
-enum PropertyAccessType { LOAD, STORE };
-
-
-class Range final : public ZoneObject {
- public:
- Range()
- : lower_(kMinInt),
- upper_(kMaxInt),
- next_(NULL),
- can_be_minus_zero_(false) { }
-
- Range(int32_t lower, int32_t upper)
- : lower_(lower),
- upper_(upper),
- next_(NULL),
- can_be_minus_zero_(false) { }
-
- int32_t upper() const { return upper_; }
- int32_t lower() const { return lower_; }
- Range* next() const { return next_; }
- Range* CopyClearLower(Zone* zone) const {
- return new(zone) Range(kMinInt, upper_);
- }
- Range* CopyClearUpper(Zone* zone) const {
- return new(zone) Range(lower_, kMaxInt);
- }
- Range* Copy(Zone* zone) const {
- Range* result = new(zone) Range(lower_, upper_);
- result->set_can_be_minus_zero(CanBeMinusZero());
- return result;
- }
- int32_t Mask() const;
- void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
- bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
- bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
- bool CanBeNegative() const { return lower_ < 0; }
- bool CanBePositive() const { return upper_ > 0; }
- bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
- bool IsMostGeneric() const {
- return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
- }
- bool IsInSmiRange() const {
- return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
- }
- void ClampToSmi() {
- lower_ = Max(lower_, Smi::kMinValue);
- upper_ = Min(upper_, Smi::kMaxValue);
- }
- void KeepOrder();
-#ifdef DEBUG
- void Verify() const;
-#endif
-
- void StackUpon(Range* other) {
- Intersect(other);
- next_ = other;
- }
-
- void Intersect(Range* other);
- void Union(Range* other);
- void CombinedMax(Range* other);
- void CombinedMin(Range* other);
-
- void AddConstant(int32_t value);
- void Sar(int32_t value);
- void Shl(int32_t value);
- bool AddAndCheckOverflow(const Representation& r, Range* other);
- bool SubAndCheckOverflow(const Representation& r, Range* other);
- bool MulAndCheckOverflow(const Representation& r, Range* other);
-
- private:
- int32_t lower_;
- int32_t upper_;
- Range* next_;
- bool can_be_minus_zero_;
-};
-
-
-class HUseListNode: public ZoneObject {
- public:
- HUseListNode(HValue* value, int index, HUseListNode* tail)
- : tail_(tail), value_(value), index_(index) {
- }
-
- HUseListNode* tail();
- HValue* value() const { return value_; }
- int index() const { return index_; }
-
- void set_tail(HUseListNode* list) { tail_ = list; }
-
-#ifdef DEBUG
- void Zap() {
- tail_ = reinterpret_cast<HUseListNode*>(1);
- value_ = NULL;
- index_ = -1;
- }
-#endif
-
- private:
- HUseListNode* tail_;
- HValue* value_;
- int index_;
-};
-
-
-// We reuse use list nodes behind the scenes as uses are added and deleted.
-// This class is the safe way to iterate uses while deleting them.
-class HUseIterator final BASE_EMBEDDED {
- public:
- bool Done() { return current_ == NULL; }
- void Advance();
-
- HValue* value() {
- DCHECK(!Done());
- return value_;
- }
-
- int index() {
- DCHECK(!Done());
- return index_;
- }
-
- private:
- explicit HUseIterator(HUseListNode* head);
-
- HUseListNode* current_;
- HUseListNode* next_;
- HValue* value_;
- int index_;
-
- friend class HValue;
-};
-
-
-// All tracked flags should appear before untracked ones.
-enum GVNFlag {
- // Declare global value numbering flags.
-#define DECLARE_FLAG(Type) k##Type,
- GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
- GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
-#undef DECLARE_FLAG
-#define COUNT_FLAG(Type) + 1
- kNumberOfTrackedSideEffects = 0 GVN_TRACKED_FLAG_LIST(COUNT_FLAG),
- kNumberOfUntrackedSideEffects = 0 GVN_UNTRACKED_FLAG_LIST(COUNT_FLAG),
-#undef COUNT_FLAG
- kNumberOfFlags = kNumberOfTrackedSideEffects + kNumberOfUntrackedSideEffects
-};
-
-
-static inline GVNFlag GVNFlagFromInt(int i) {
- DCHECK(i >= 0);
- DCHECK(i < kNumberOfFlags);
- return static_cast<GVNFlag>(i);
-}
-
-
-class DecompositionResult final BASE_EMBEDDED {
- public:
- DecompositionResult() : base_(NULL), offset_(0), scale_(0) {}
-
- HValue* base() { return base_; }
- int offset() { return offset_; }
- int scale() { return scale_; }
-
- bool Apply(HValue* other_base, int other_offset, int other_scale = 0) {
- if (base_ == NULL) {
- base_ = other_base;
- offset_ = other_offset;
- scale_ = other_scale;
- return true;
- } else {
- if (scale_ == 0) {
- base_ = other_base;
- offset_ += other_offset;
- scale_ = other_scale;
- return true;
- } else {
- return false;
- }
- }
- }
-
- void SwapValues(HValue** other_base, int* other_offset, int* other_scale) {
- swap(&base_, other_base);
- swap(&offset_, other_offset);
- swap(&scale_, other_scale);
- }
-
- private:
- template <class T> void swap(T* a, T* b) {
- T c(*a);
- *a = *b;
- *b = c;
- }
-
- HValue* base_;
- int offset_;
- int scale_;
-};
-
-
-typedef EnumSet<GVNFlag, int32_t> GVNFlagSet;
-
-
-class HValue : public ZoneObject {
- public:
- static const int kNoNumber = -1;
-
- enum Flag {
- kFlexibleRepresentation,
- kCannotBeTagged,
- // Participate in Global Value Numbering, i.e. elimination of
- // unnecessary recomputations. If an instruction sets this flag, it must
- // implement DataEquals(), which will be used to determine if other
- // occurrences of the instruction are indeed the same.
- kUseGVN,
- // Track instructions that are dominating side effects. If an instruction
- // sets this flag, it must implement HandleSideEffectDominator() and should
- // indicate which side effects to track by setting GVN flags.
- kTrackSideEffectDominators,
- kCanOverflow,
- kBailoutOnMinusZero,
- kCanBeDivByZero,
- kLeftCanBeMinInt,
- kLeftCanBeNegative,
- kLeftCanBePositive,
- kAllowUndefinedAsNaN,
- kIsArguments,
- kTruncatingToInt32,
- kAllUsesTruncatingToInt32,
- kTruncatingToSmi,
- kAllUsesTruncatingToSmi,
- // Set after an instruction is killed.
- kIsDead,
- // Instructions that are allowed to produce full range unsigned integer
- // values are marked with kUint32 flag. If arithmetic shift or a load from
- // EXTERNAL_UINT32_ELEMENTS array is not marked with this flag
- // it will deoptimize if result does not fit into signed integer range.
- // HGraph::ComputeSafeUint32Operations is responsible for setting this
- // flag.
- kUint32,
- kHasNoObservableSideEffects,
- // Indicates an instruction shouldn't be replaced by optimization, this flag
- // is useful to set in cases where recomputing a value is cheaper than
- // extending the value's live range and spilling it.
- kCantBeReplaced,
- // Indicates the instruction is live during dead code elimination.
- kIsLive,
-
- // HEnvironmentMarkers are deleted before dead code
- // elimination takes place, so they can repurpose the kIsLive flag:
- kEndsLiveRange = kIsLive,
-
- // TODO(everyone): Don't forget to update this!
- kLastFlag = kIsLive
- };
-
- STATIC_ASSERT(kLastFlag < kBitsPerInt);
-
- static HValue* cast(HValue* value) { return value; }
-
- enum Opcode {
- // Declare a unique enum value for each hydrogen instruction.
- #define DECLARE_OPCODE(type) k##type,
- HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
- kPhi
- #undef DECLARE_OPCODE
- };
- virtual Opcode opcode() const = 0;
-
- // Declare a non-virtual predicates for each concrete HInstruction or HValue.
- #define DECLARE_PREDICATE(type) \
- bool Is##type() const { return opcode() == k##type; }
- HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
- #undef DECLARE_PREDICATE
- bool IsPhi() const { return opcode() == kPhi; }
-
- // Declare virtual predicates for abstract HInstruction or HValue
- #define DECLARE_PREDICATE(type) \
- virtual bool Is##type() const { return false; }
- HYDROGEN_ABSTRACT_INSTRUCTION_LIST(DECLARE_PREDICATE)
- #undef DECLARE_PREDICATE
-
- bool IsBitwiseBinaryShift() {
- return IsShl() || IsShr() || IsSar();
- }
-
- explicit HValue(HType type = HType::Tagged())
- : block_(NULL),
- id_(kNoNumber),
- type_(type),
- use_list_(NULL),
- range_(NULL),
-#ifdef DEBUG
- range_poisoned_(false),
-#endif
- flags_(0) {}
- virtual ~HValue() {}
-
- virtual SourcePosition position() const { return SourcePosition::Unknown(); }
- virtual SourcePosition operand_position(int index) const {
- return position();
- }
-
- HBasicBlock* block() const { return block_; }
- void SetBlock(HBasicBlock* block);
-
- // Note: Never call this method for an unlinked value.
- Isolate* isolate() const;
-
- int id() const { return id_; }
- void set_id(int id) { id_ = id; }
-
- HUseIterator uses() const { return HUseIterator(use_list_); }
-
- virtual bool EmitAtUses() { return false; }
-
- Representation representation() const { return representation_; }
- void ChangeRepresentation(Representation r) {
- DCHECK(CheckFlag(kFlexibleRepresentation));
- DCHECK(!CheckFlag(kCannotBeTagged) || !r.IsTagged());
- RepresentationChanged(r);
- representation_ = r;
- if (r.IsTagged()) {
- // Tagged is the bottom of the lattice, don't go any further.
- ClearFlag(kFlexibleRepresentation);
- }
- }
- virtual void AssumeRepresentation(Representation r);
-
- virtual Representation KnownOptimalRepresentation() {
- Representation r = representation();
- if (r.IsTagged()) {
- HType t = type();
- if (t.IsSmi()) return Representation::Smi();
- if (t.IsHeapNumber()) return Representation::Double();
- if (t.IsHeapObject()) return r;
- return Representation::None();
- }
- return r;
- }
-
- HType type() const { return type_; }
- void set_type(HType new_type) {
- DCHECK(new_type.IsSubtypeOf(type_));
- type_ = new_type;
- }
-
- // There are HInstructions that do not really change a value, they
- // only add pieces of information to it (like bounds checks, map checks,
- // smi checks...).
- // We call these instructions "informative definitions", or "iDef".
- // One of the iDef operands is special because it is the value that is
- // "transferred" to the output, we call it the "redefined operand".
- // If an HValue is an iDef it must override RedefinedOperandIndex() so that
- // it does not return kNoRedefinedOperand;
- static const int kNoRedefinedOperand = -1;
- virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; }
- bool IsInformativeDefinition() {
- return RedefinedOperandIndex() != kNoRedefinedOperand;
- }
- HValue* RedefinedOperand() {
- int index = RedefinedOperandIndex();
- return index == kNoRedefinedOperand ? NULL : OperandAt(index);
- }
-
- bool CanReplaceWithDummyUses();
-
- virtual int argument_delta() const { return 0; }
-
- // A purely informative definition is an idef that will not emit code and
- // should therefore be removed from the graph in the RestoreActualValues
- // phase (so that live ranges will be shorter).
- virtual bool IsPurelyInformativeDefinition() { return false; }
-
- // This method must always return the original HValue SSA definition,
- // regardless of any chain of iDefs of this value.
- HValue* ActualValue() {
- HValue* value = this;
- int index;
- while ((index = value->RedefinedOperandIndex()) != kNoRedefinedOperand) {
- value = value->OperandAt(index);
- }
- return value;
- }
-
- bool IsInteger32Constant();
- int32_t GetInteger32Constant();
- bool EqualsInteger32Constant(int32_t value);
-
- bool IsDefinedAfter(HBasicBlock* other) const;
-
- // Operands.
- virtual int OperandCount() const = 0;
- virtual HValue* OperandAt(int index) const = 0;
- void SetOperandAt(int index, HValue* value);
-
- void DeleteAndReplaceWith(HValue* other);
- void ReplaceAllUsesWith(HValue* other);
- bool HasNoUses() const { return use_list_ == NULL; }
- bool HasOneUse() const {
- return use_list_ != NULL && use_list_->tail() == NULL;
- }
- bool HasMultipleUses() const {
- return use_list_ != NULL && use_list_->tail() != NULL;
- }
- int UseCount() const;
-
- // Mark this HValue as dead and to be removed from other HValues' use lists.
- void Kill();
-
- int flags() const { return flags_; }
- void SetFlag(Flag f) { flags_ |= (1 << f); }
- void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
- bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
- void CopyFlag(Flag f, HValue* other) {
- if (other->CheckFlag(f)) SetFlag(f);
- }
-
- // Returns true if the flag specified is set for all uses, false otherwise.
- bool CheckUsesForFlag(Flag f) const;
- // Same as before and the first one without the flag is returned in value.
- bool CheckUsesForFlag(Flag f, HValue** value) const;
- // Returns true if the flag specified is set for all uses, and this set
- // of uses is non-empty.
- bool HasAtLeastOneUseWithFlagAndNoneWithout(Flag f) const;
-
- GVNFlagSet ChangesFlags() const { return changes_flags_; }
- GVNFlagSet DependsOnFlags() const { return depends_on_flags_; }
- void SetChangesFlag(GVNFlag f) { changes_flags_.Add(f); }
- void SetDependsOnFlag(GVNFlag f) { depends_on_flags_.Add(f); }
- void ClearChangesFlag(GVNFlag f) { changes_flags_.Remove(f); }
- void ClearDependsOnFlag(GVNFlag f) { depends_on_flags_.Remove(f); }
- bool CheckChangesFlag(GVNFlag f) const {
- return changes_flags_.Contains(f);
- }
- bool CheckDependsOnFlag(GVNFlag f) const {
- return depends_on_flags_.Contains(f);
- }
- void SetAllSideEffects() { changes_flags_.Add(AllSideEffectsFlagSet()); }
- void ClearAllSideEffects() {
- changes_flags_.Remove(AllSideEffectsFlagSet());
- }
- bool HasSideEffects() const {
- return changes_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
- }
- bool HasObservableSideEffects() const {
- return !CheckFlag(kHasNoObservableSideEffects) &&
- changes_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
- }
-
- GVNFlagSet SideEffectFlags() const {
- GVNFlagSet result = ChangesFlags();
- result.Intersect(AllSideEffectsFlagSet());
- return result;
- }
-
- GVNFlagSet ObservableChangesFlags() const {
- GVNFlagSet result = ChangesFlags();
- result.Intersect(AllObservableSideEffectsFlagSet());
- return result;
- }
-
- Range* range() const {
- DCHECK(!range_poisoned_);
- return range_;
- }
- bool HasRange() const {
- DCHECK(!range_poisoned_);
- return range_ != NULL;
- }
-#ifdef DEBUG
- void PoisonRange() { range_poisoned_ = true; }
-#endif
- void AddNewRange(Range* r, Zone* zone);
- void RemoveLastAddedRange();
- void ComputeInitialRange(Zone* zone);
-
- // Escape analysis helpers.
- virtual bool HasEscapingOperandAt(int index) { return true; }
- virtual bool HasOutOfBoundsAccess(int size) { return false; }
-
- // Representation helpers.
- virtual Representation observed_input_representation(int index) {
- return Representation::None();
- }
- virtual Representation RequiredInputRepresentation(int index) = 0;
- virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
-
- // This gives the instruction an opportunity to replace itself with an
- // instruction that does the same in some better way. To replace an
- // instruction with a new one, first add the new instruction to the graph,
- // then return it. Return NULL to have the instruction deleted.
- virtual HValue* Canonicalize() { return this; }
-
- bool Equals(HValue* other);
- virtual intptr_t Hashcode();
-
- // Compute unique ids upfront that is safe wrt GC and concurrent compilation.
- virtual void FinalizeUniqueness() { }
-
- // Printing support.
- virtual std::ostream& PrintTo(std::ostream& os) const = 0; // NOLINT
-
- const char* Mnemonic() const;
-
- // Type information helpers.
- bool HasMonomorphicJSObjectType();
-
- // TODO(mstarzinger): For now instructions can override this function to
- // specify statically known types, once HType can convey more information
- // it should be based on the HType.
- virtual Handle<Map> GetMonomorphicJSObjectMap() { return Handle<Map>(); }
-
- // Updated the inferred type of this instruction and returns true if
- // it has changed.
- bool UpdateInferredType();
-
- virtual HType CalculateInferredType();
-
- // This function must be overridden for instructions which have the
- // kTrackSideEffectDominators flag set, to track instructions that are
- // dominating side effects.
- // It returns true if it removed an instruction which had side effects.
- virtual bool HandleSideEffectDominator(GVNFlag side_effect,
- HValue* dominator) {
- UNREACHABLE();
- return false;
- }
-
- // Check if this instruction has some reason that prevents elimination.
- bool CannotBeEliminated() const {
- return HasObservableSideEffects() || !IsDeletable();
- }
-
-#ifdef DEBUG
- virtual void Verify() = 0;
-#endif
-
- virtual bool TryDecompose(DecompositionResult* decomposition) {
- if (RedefinedOperand() != NULL) {
- return RedefinedOperand()->TryDecompose(decomposition);
- } else {
- return false;
- }
- }
-
- // Returns true conservatively if the program might be able to observe a
- // ToString() operation on this value.
- bool ToStringCanBeObserved() const {
- return ToStringOrToNumberCanBeObserved();
- }
-
- // Returns true conservatively if the program might be able to observe a
- // ToNumber() operation on this value.
- bool ToNumberCanBeObserved() const {
- return ToStringOrToNumberCanBeObserved();
- }
-
- MinusZeroMode GetMinusZeroMode() {
- return CheckFlag(kBailoutOnMinusZero)
- ? FAIL_ON_MINUS_ZERO : TREAT_MINUS_ZERO_AS_ZERO;
- }
-
- protected:
- // This function must be overridden for instructions with flag kUseGVN, to
- // compare the non-Operand parts of the instruction.
- virtual bool DataEquals(HValue* other) {
- UNREACHABLE();
- return false;
- }
-
- bool ToStringOrToNumberCanBeObserved() const {
- if (type().IsTaggedPrimitive()) return false;
- if (type().IsJSObject()) return true;
- return !representation().IsSmiOrInteger32() && !representation().IsDouble();
- }
-
- virtual Representation RepresentationFromInputs() {
- return representation();
- }
- virtual Representation RepresentationFromUses();
- Representation RepresentationFromUseRequirements();
- bool HasNonSmiUse();
- virtual void UpdateRepresentation(Representation new_rep,
- HInferRepresentationPhase* h_infer,
- const char* reason);
- void AddDependantsToWorklist(HInferRepresentationPhase* h_infer);
-
- virtual void RepresentationChanged(Representation to) { }
-
- virtual Range* InferRange(Zone* zone);
- virtual void DeleteFromGraph() = 0;
- virtual void InternalSetOperandAt(int index, HValue* value) = 0;
- void clear_block() {
- DCHECK(block_ != NULL);
- block_ = NULL;
- }
-
- void set_representation(Representation r) {
- DCHECK(representation_.IsNone() && !r.IsNone());
- representation_ = r;
- }
-
- static GVNFlagSet AllFlagSet() {
- GVNFlagSet result;
-#define ADD_FLAG(Type) result.Add(k##Type);
- GVN_TRACKED_FLAG_LIST(ADD_FLAG)
- GVN_UNTRACKED_FLAG_LIST(ADD_FLAG)
-#undef ADD_FLAG
- return result;
- }
-
- // A flag mask to mark an instruction as having arbitrary side effects.
- static GVNFlagSet AllSideEffectsFlagSet() {
- GVNFlagSet result = AllFlagSet();
- result.Remove(kOsrEntries);
- return result;
- }
- friend std::ostream& operator<<(std::ostream& os, const ChangesOf& v);
-
- // A flag mask of all side effects that can make observable changes in
- // an executing program (i.e. are not safe to repeat, move or remove);
- static GVNFlagSet AllObservableSideEffectsFlagSet() {
- GVNFlagSet result = AllFlagSet();
- result.Remove(kNewSpacePromotion);
- result.Remove(kElementsKind);
- result.Remove(kElementsPointer);
- result.Remove(kMaps);
- return result;
- }
-
- // Remove the matching use from the use list if present. Returns the
- // removed list node or NULL.
- HUseListNode* RemoveUse(HValue* value, int index);
-
- void RegisterUse(int index, HValue* new_value);
-
- HBasicBlock* block_;
-
- // The id of this instruction in the hydrogen graph, assigned when first
- // added to the graph. Reflects creation order.
- int id_;
-
- Representation representation_;
- HType type_;
- HUseListNode* use_list_;
- Range* range_;
-#ifdef DEBUG
- bool range_poisoned_;
-#endif
- int flags_;
- GVNFlagSet changes_flags_;
- GVNFlagSet depends_on_flags_;
-
- private:
- virtual bool IsDeletable() const { return false; }
-
- DISALLOW_COPY_AND_ASSIGN(HValue);
-};
-
-// Support for printing various aspects of an HValue.
-struct NameOf {
- explicit NameOf(const HValue* const v) : value(v) {}
- const HValue* value;
-};
-
-
-struct TypeOf {
- explicit TypeOf(const HValue* const v) : value(v) {}
- const HValue* value;
-};
-
-
-struct ChangesOf {
- explicit ChangesOf(const HValue* const v) : value(v) {}
- const HValue* value;
-};
-
-
-std::ostream& operator<<(std::ostream& os, const HValue& v);
-std::ostream& operator<<(std::ostream& os, const NameOf& v);
-std::ostream& operator<<(std::ostream& os, const TypeOf& v);
-std::ostream& operator<<(std::ostream& os, const ChangesOf& v);
-
-
-#define DECLARE_INSTRUCTION_FACTORY_P0(I) \
- static I* New(Isolate* isolate, Zone* zone, HValue* context) { \
- return new (zone) I(); \
- }
-
-#define DECLARE_INSTRUCTION_FACTORY_P1(I, P1) \
- static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1) { \
- return new (zone) I(p1); \
- }
-
-#define DECLARE_INSTRUCTION_FACTORY_P2(I, P1, P2) \
- static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2) { \
- return new (zone) I(p1, p2); \
- }
-
-#define DECLARE_INSTRUCTION_FACTORY_P3(I, P1, P2, P3) \
- static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
- P3 p3) { \
- return new (zone) I(p1, p2, p3); \
- }
-
-#define DECLARE_INSTRUCTION_FACTORY_P4(I, P1, P2, P3, P4) \
- static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
- P3 p3, P4 p4) { \
- return new (zone) I(p1, p2, p3, p4); \
- }
-
-#define DECLARE_INSTRUCTION_FACTORY_P5(I, P1, P2, P3, P4, P5) \
- static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
- P3 p3, P4 p4, P5 p5) { \
- return new (zone) I(p1, p2, p3, p4, p5); \
- }
-
-#define DECLARE_INSTRUCTION_FACTORY_P6(I, P1, P2, P3, P4, P5, P6) \
- static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
- P3 p3, P4 p4, P5 p5, P6 p6) { \
- return new (zone) I(p1, p2, p3, p4, p5, p6); \
- }
-
-#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P0(I) \
- static I* New(Isolate* isolate, Zone* zone, HValue* context) { \
- return new (zone) I(context); \
- }
-
-#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(I, P1) \
- static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1) { \
- return new (zone) I(context, p1); \
- }
-
-#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(I, P1, P2) \
- static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2) { \
- return new (zone) I(context, p1, p2); \
- }
-
-#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(I, P1, P2, P3) \
- static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
- P3 p3) { \
- return new (zone) I(context, p1, p2, p3); \
- }
-
-#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(I, P1, P2, P3, P4) \
- static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
- P3 p3, P4 p4) { \
- return new (zone) I(context, p1, p2, p3, p4); \
- }
-
-#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(I, P1, P2, P3, P4, P5) \
- static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
- P3 p3, P4 p4, P5 p5) { \
- return new (zone) I(context, p1, p2, p3, p4, p5); \
- }
-
-#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P6(I, P1, P2, P3, P4, P5, P6) \
- static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
- P3 p3, P4 p4, P5 p5, P6 p6) { \
- return new (zone) I(context, p1, p2, p3, p4, p5, p6); \
- }
-
-
-// A helper class to represent per-operand position information attached to
-// the HInstruction in the compact form. Uses tagging to distinguish between
-// case when only instruction's position is available and case when operands'
-// positions are also available.
-// In the first case it contains intruction's position as a tagged value.
-// In the second case it points to an array which contains instruction's
-// position and operands' positions.
-class HPositionInfo {
- public:
- explicit HPositionInfo(int pos) : data_(TagPosition(pos)) { }
-
- SourcePosition position() const {
- if (has_operand_positions()) {
- return operand_positions()[kInstructionPosIndex];
- }
- return SourcePosition::FromRaw(static_cast<int>(UntagPosition(data_)));
- }
-
- void set_position(SourcePosition pos) {
- if (has_operand_positions()) {
- operand_positions()[kInstructionPosIndex] = pos;
- } else {
- data_ = TagPosition(pos.raw());
- }
- }
-
- void ensure_storage_for_operand_positions(Zone* zone, int operand_count) {
- if (has_operand_positions()) {
- return;
- }
-
- const int length = kFirstOperandPosIndex + operand_count;
- SourcePosition* positions = zone->NewArray<SourcePosition>(length);
- for (int i = 0; i < length; i++) {
- positions[i] = SourcePosition::Unknown();
- }
-
- const SourcePosition pos = position();
- data_ = reinterpret_cast<intptr_t>(positions);
- set_position(pos);
-
- DCHECK(has_operand_positions());
- }
-
- SourcePosition operand_position(int idx) const {
- if (!has_operand_positions()) {
- return position();
- }
- return *operand_position_slot(idx);
- }
-
- void set_operand_position(int idx, SourcePosition pos) {
- *operand_position_slot(idx) = pos;
- }
-
- private:
- static const intptr_t kInstructionPosIndex = 0;
- static const intptr_t kFirstOperandPosIndex = 1;
-
- SourcePosition* operand_position_slot(int idx) const {
- DCHECK(has_operand_positions());
- return &(operand_positions()[kFirstOperandPosIndex + idx]);
- }
-
- bool has_operand_positions() const {
- return !IsTaggedPosition(data_);
- }
-
- SourcePosition* operand_positions() const {
- DCHECK(has_operand_positions());
- return reinterpret_cast<SourcePosition*>(data_);
- }
-
- static const intptr_t kPositionTag = 1;
- static const intptr_t kPositionShift = 1;
- static bool IsTaggedPosition(intptr_t val) {
- return (val & kPositionTag) != 0;
- }
- static intptr_t UntagPosition(intptr_t val) {
- DCHECK(IsTaggedPosition(val));
- return val >> kPositionShift;
- }
- static intptr_t TagPosition(intptr_t val) {
- const intptr_t result = (val << kPositionShift) | kPositionTag;
- DCHECK(UntagPosition(result) == val);
- return result;
- }
-
- intptr_t data_;
-};
-
-
-class HInstruction : public HValue {
- public:
- HInstruction* next() const { return next_; }
- HInstruction* previous() const { return previous_; }
-
- std::ostream& PrintTo(std::ostream& os) const override; // NOLINT
- virtual std::ostream& PrintDataTo(std::ostream& os) const; // NOLINT
-
- bool IsLinked() const { return block() != NULL; }
- void Unlink();
-
- void InsertBefore(HInstruction* next);
-
- template<class T> T* Prepend(T* instr) {
- instr->InsertBefore(this);
- return instr;
- }
-
- void InsertAfter(HInstruction* previous);
-
- template<class T> T* Append(T* instr) {
- instr->InsertAfter(this);
- return instr;
- }
-
- // The position is a write-once variable.
- SourcePosition position() const override {
- return SourcePosition(position_.position());
- }
- bool has_position() const {
- return !position().IsUnknown();
- }
- void set_position(SourcePosition position) {
- DCHECK(!has_position());
- DCHECK(!position.IsUnknown());
- position_.set_position(position);
- }
-
- SourcePosition operand_position(int index) const override {
- const SourcePosition pos = position_.operand_position(index);
- return pos.IsUnknown() ? position() : pos;
- }
- void set_operand_position(Zone* zone, int index, SourcePosition pos) {
- DCHECK(0 <= index && index < OperandCount());
- position_.ensure_storage_for_operand_positions(zone, OperandCount());
- position_.set_operand_position(index, pos);
- }
-
- bool Dominates(HInstruction* other);
- bool CanTruncateToSmi() const { return CheckFlag(kTruncatingToSmi); }
- bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); }
-
- virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
-
-#ifdef DEBUG
- void Verify() override;
-#endif
-
- bool CanDeoptimize();
-
- virtual bool HasStackCheck() { return false; }
-
- DECLARE_ABSTRACT_INSTRUCTION(Instruction)
-
- protected:
- explicit HInstruction(HType type = HType::Tagged())
- : HValue(type),
- next_(NULL),
- previous_(NULL),
- position_(RelocInfo::kNoPosition) {
- SetDependsOnFlag(kOsrEntries);
- }
-
- void DeleteFromGraph() override { Unlink(); }
-
- private:
- void InitializeAsFirst(HBasicBlock* block) {
- DCHECK(!IsLinked());
- SetBlock(block);
- }
-
- HInstruction* next_;
- HInstruction* previous_;
- HPositionInfo position_;
-
- friend class HBasicBlock;
-};
-
-
-template<int V>
-class HTemplateInstruction : public HInstruction {
- public:
- int OperandCount() const final { return V; }
- HValue* OperandAt(int i) const final { return inputs_[i]; }
-
- protected:
- explicit HTemplateInstruction(HType type = HType::Tagged())
- : HInstruction(type) {}
-
- void InternalSetOperandAt(int i, HValue* value) final { inputs_[i] = value; }
-
- private:
- EmbeddedContainer<HValue*, V> inputs_;
-};
-
-
-class HControlInstruction : public HInstruction {
- public:
- virtual HBasicBlock* SuccessorAt(int i) const = 0;
- virtual int SuccessorCount() const = 0;
- virtual void SetSuccessorAt(int i, HBasicBlock* block) = 0;
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- virtual bool KnownSuccessorBlock(HBasicBlock** block) {
- *block = NULL;
- return false;
- }
-
- HBasicBlock* FirstSuccessor() {
- return SuccessorCount() > 0 ? SuccessorAt(0) : NULL;
- }
- HBasicBlock* SecondSuccessor() {
- return SuccessorCount() > 1 ? SuccessorAt(1) : NULL;
- }
-
- void Not() {
- HBasicBlock* swap = SuccessorAt(0);
- SetSuccessorAt(0, SuccessorAt(1));
- SetSuccessorAt(1, swap);
- }
-
- DECLARE_ABSTRACT_INSTRUCTION(ControlInstruction)
-};
-
-
-class HSuccessorIterator final BASE_EMBEDDED {
- public:
- explicit HSuccessorIterator(const HControlInstruction* instr)
- : instr_(instr), current_(0) {}
-
- bool Done() { return current_ >= instr_->SuccessorCount(); }
- HBasicBlock* Current() { return instr_->SuccessorAt(current_); }
- void Advance() { current_++; }
-
- private:
- const HControlInstruction* instr_;
- int current_;
-};
-
-
-template<int S, int V>
-class HTemplateControlInstruction : public HControlInstruction {
- public:
- int SuccessorCount() const override { return S; }
- HBasicBlock* SuccessorAt(int i) const override { return successors_[i]; }
- void SetSuccessorAt(int i, HBasicBlock* block) override {
- successors_[i] = block;
- }
-
- int OperandCount() const override { return V; }
- HValue* OperandAt(int i) const override { return inputs_[i]; }
-
-
- protected:
- void InternalSetOperandAt(int i, HValue* value) override {
- inputs_[i] = value;
- }
-
- private:
- EmbeddedContainer<HBasicBlock*, S> successors_;
- EmbeddedContainer<HValue*, V> inputs_;
-};
-
-
-class HBlockEntry final : public HTemplateInstruction<0> {
- public:
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(BlockEntry)
-};
-
-
-class HDummyUse final : public HTemplateInstruction<1> {
- public:
- explicit HDummyUse(HValue* value)
- : HTemplateInstruction<1>(HType::Smi()) {
- SetOperandAt(0, value);
- // Pretend to be a Smi so that the HChange instructions inserted
- // before any use generate as little code as possible.
- set_representation(Representation::Tagged());
- }
-
- HValue* value() const { return OperandAt(0); }
-
- bool HasEscapingOperandAt(int index) override { return false; }
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- DECLARE_CONCRETE_INSTRUCTION(DummyUse);
-};
-
-
-// Inserts an int3/stop break instruction for debugging purposes.
-class HDebugBreak final : public HTemplateInstruction<0> {
- public:
- DECLARE_INSTRUCTION_FACTORY_P0(HDebugBreak);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(DebugBreak)
-};
-
-
-class HPrologue final : public HTemplateInstruction<0> {
- public:
- static HPrologue* New(Zone* zone) { return new (zone) HPrologue(); }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Prologue)
-};
-
-
-class HGoto final : public HTemplateControlInstruction<1, 0> {
- public:
- explicit HGoto(HBasicBlock* target) {
- SetSuccessorAt(0, target);
- }
-
- bool KnownSuccessorBlock(HBasicBlock** block) override {
- *block = FirstSuccessor();
- return true;
- }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- DECLARE_CONCRETE_INSTRUCTION(Goto)
-};
-
-
-class HDeoptimize final : public HTemplateControlInstruction<1, 0> {
- public:
- static HDeoptimize* New(Isolate* isolate, Zone* zone, HValue* context,
- Deoptimizer::DeoptReason reason,
- Deoptimizer::BailoutType type,
- HBasicBlock* unreachable_continuation) {
- return new(zone) HDeoptimize(reason, type, unreachable_continuation);
- }
-
- bool KnownSuccessorBlock(HBasicBlock** block) override {
- *block = NULL;
- return true;
- }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
-
- Deoptimizer::DeoptReason reason() const { return reason_; }
- Deoptimizer::BailoutType type() { return type_; }
-
- DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
-
- private:
- explicit HDeoptimize(Deoptimizer::DeoptReason reason,
- Deoptimizer::BailoutType type,
- HBasicBlock* unreachable_continuation)
- : reason_(reason), type_(type) {
- SetSuccessorAt(0, unreachable_continuation);
- }
-
- Deoptimizer::DeoptReason reason_;
- Deoptimizer::BailoutType type_;
-};
-
-
-class HUnaryControlInstruction : public HTemplateControlInstruction<2, 1> {
- public:
- HUnaryControlInstruction(HValue* value,
- HBasicBlock* true_target,
- HBasicBlock* false_target) {
- SetOperandAt(0, value);
- SetSuccessorAt(0, true_target);
- SetSuccessorAt(1, false_target);
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- HValue* value() const { return OperandAt(0); }
-};
-
-
-class HBranch final : public HUnaryControlInstruction {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HBranch, HValue*);
- DECLARE_INSTRUCTION_FACTORY_P2(HBranch, HValue*,
- ToBooleanStub::Types);
- DECLARE_INSTRUCTION_FACTORY_P4(HBranch, HValue*,
- ToBooleanStub::Types,
- HBasicBlock*, HBasicBlock*);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
- Representation observed_input_representation(int index) override;
-
- bool KnownSuccessorBlock(HBasicBlock** block) override;
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- ToBooleanStub::Types expected_input_types() const {
- return expected_input_types_;
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Branch)
-
- private:
- HBranch(HValue* value,
- ToBooleanStub::Types expected_input_types = ToBooleanStub::Types(),
- HBasicBlock* true_target = NULL,
- HBasicBlock* false_target = NULL)
- : HUnaryControlInstruction(value, true_target, false_target),
- expected_input_types_(expected_input_types) {
- SetFlag(kAllowUndefinedAsNaN);
- }
-
- ToBooleanStub::Types expected_input_types_;
-};
-
-
-class HCompareMap final : public HUnaryControlInstruction {
- public:
- DECLARE_INSTRUCTION_FACTORY_P2(HCompareMap, HValue*, Handle<Map>);
- DECLARE_INSTRUCTION_FACTORY_P4(HCompareMap, HValue*, Handle<Map>,
- HBasicBlock*, HBasicBlock*);
-
- bool KnownSuccessorBlock(HBasicBlock** block) override {
- if (known_successor_index() != kNoKnownSuccessorIndex) {
- *block = SuccessorAt(known_successor_index());
- return true;
- }
- *block = NULL;
- return false;
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- static const int kNoKnownSuccessorIndex = -1;
- int known_successor_index() const {
- return KnownSuccessorIndexField::decode(bit_field_) -
- kInternalKnownSuccessorOffset;
- }
- void set_known_successor_index(int index) {
- DCHECK(index >= 0 - kInternalKnownSuccessorOffset);
- bit_field_ = KnownSuccessorIndexField::update(
- bit_field_, index + kInternalKnownSuccessorOffset);
- }
-
- Unique<Map> map() const { return map_; }
- bool map_is_stable() const { return MapIsStableField::decode(bit_field_); }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(CompareMap)
-
- protected:
- int RedefinedOperandIndex() override { return 0; }
-
- private:
- HCompareMap(HValue* value, Handle<Map> map, HBasicBlock* true_target = NULL,
- HBasicBlock* false_target = NULL)
- : HUnaryControlInstruction(value, true_target, false_target),
- bit_field_(KnownSuccessorIndexField::encode(
- kNoKnownSuccessorIndex + kInternalKnownSuccessorOffset) |
- MapIsStableField::encode(map->is_stable())),
- map_(Unique<Map>::CreateImmovable(map)) {
- set_representation(Representation::Tagged());
- }
-
- // BitFields can only store unsigned values, so use an offset.
- // Adding kInternalKnownSuccessorOffset must yield an unsigned value.
- static const int kInternalKnownSuccessorOffset = 1;
- STATIC_ASSERT(kNoKnownSuccessorIndex + kInternalKnownSuccessorOffset >= 0);
-
- class KnownSuccessorIndexField : public BitField<int, 0, 31> {};
- class MapIsStableField : public BitField<bool, 31, 1> {};
-
- uint32_t bit_field_;
- Unique<Map> map_;
-};
-
-
-class HContext final : public HTemplateInstruction<0> {
- public:
- static HContext* New(Zone* zone) {
- return new(zone) HContext();
- }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Context)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- private:
- HContext() {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- }
-
- bool IsDeletable() const override { return true; }
-};
-
-
-class HReturn final : public HTemplateControlInstruction<0, 3> {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HReturn, HValue*, HValue*);
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HReturn, HValue*);
-
- Representation RequiredInputRepresentation(int index) override {
- // TODO(titzer): require an Int32 input for faster returns.
- if (index == 2) return Representation::Smi();
- return Representation::Tagged();
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- HValue* value() const { return OperandAt(0); }
- HValue* context() const { return OperandAt(1); }
- HValue* parameter_count() const { return OperandAt(2); }
-
- DECLARE_CONCRETE_INSTRUCTION(Return)
-
- private:
- HReturn(HValue* context, HValue* value, HValue* parameter_count = 0) {
- SetOperandAt(0, value);
- SetOperandAt(1, context);
- SetOperandAt(2, parameter_count);
- }
-};
-
-
-class HAbnormalExit final : public HTemplateControlInstruction<0, 0> {
- public:
- DECLARE_INSTRUCTION_FACTORY_P0(HAbnormalExit);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(AbnormalExit)
- private:
- HAbnormalExit() {}
-};
-
-
-class HUnaryOperation : public HTemplateInstruction<1> {
- public:
- explicit HUnaryOperation(HValue* value, HType type = HType::Tagged())
- : HTemplateInstruction<1>(type) {
- SetOperandAt(0, value);
- }
-
- static HUnaryOperation* cast(HValue* value) {
- return reinterpret_cast<HUnaryOperation*>(value);
- }
-
- HValue* value() const { return OperandAt(0); }
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-};
-
-
-class HUseConst final : public HUnaryOperation {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HUseConst, HValue*);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(UseConst)
-
- private:
- explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
-};
-
-
-class HForceRepresentation final : public HTemplateInstruction<1> {
- public:
- static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* value,
- Representation required_representation);
-
- HValue* value() const { return OperandAt(0); }
-
- Representation observed_input_representation(int index) override {
- // We haven't actually *observed* this, but it's closer to the truth
- // than 'None'.
- return representation(); // Same as the output representation.
- }
- Representation RequiredInputRepresentation(int index) override {
- return representation(); // Same as the output representation.
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation)
-
- private:
- HForceRepresentation(HValue* value, Representation required_representation) {
- SetOperandAt(0, value);
- set_representation(required_representation);
- }
-};
-
-
-class HChange final : public HUnaryOperation {
- public:
- HChange(HValue* value,
- Representation to,
- bool is_truncating_to_smi,
- bool is_truncating_to_int32)
- : HUnaryOperation(value) {
- DCHECK(!value->representation().IsNone());
- DCHECK(!to.IsNone());
- DCHECK(!value->representation().Equals(to));
- set_representation(to);
- SetFlag(kUseGVN);
- SetFlag(kCanOverflow);
- if (is_truncating_to_smi && to.IsSmi()) {
- SetFlag(kTruncatingToSmi);
- SetFlag(kTruncatingToInt32);
- }
- if (is_truncating_to_int32) SetFlag(kTruncatingToInt32);
- if (value->representation().IsSmi() || value->type().IsSmi()) {
- set_type(HType::Smi());
- } else {
- set_type(HType::TaggedNumber());
- if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
- }
- }
-
- bool can_convert_undefined_to_nan() {
- return CheckUsesForFlag(kAllowUndefinedAsNaN);
- }
-
- HType CalculateInferredType() override;
- HValue* Canonicalize() override;
-
- Representation from() const { return value()->representation(); }
- Representation to() const { return representation(); }
- bool deoptimize_on_minus_zero() const {
- return CheckFlag(kBailoutOnMinusZero);
- }
- Representation RequiredInputRepresentation(int index) override {
- return from();
- }
-
- Range* InferRange(Zone* zone) override;
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- DECLARE_CONCRETE_INSTRUCTION(Change)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- private:
- bool IsDeletable() const override {
- return !from().IsTagged() || value()->type().IsSmi();
- }
-};
-
-
-class HClampToUint8 final : public HUnaryOperation {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HClampToUint8, HValue*);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- private:
- explicit HClampToUint8(HValue* value)
- : HUnaryOperation(value) {
- set_representation(Representation::Integer32());
- SetFlag(kAllowUndefinedAsNaN);
- SetFlag(kUseGVN);
- }
-
- bool IsDeletable() const override { return true; }
-};
-
-
-class HDoubleBits final : public HUnaryOperation {
- public:
- enum Bits { HIGH, LOW };
- DECLARE_INSTRUCTION_FACTORY_P2(HDoubleBits, HValue*, Bits);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Double();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(DoubleBits)
-
- Bits bits() { return bits_; }
-
- protected:
- bool DataEquals(HValue* other) override {
- return other->IsDoubleBits() && HDoubleBits::cast(other)->bits() == bits();
- }
-
- private:
- HDoubleBits(HValue* value, Bits bits)
- : HUnaryOperation(value), bits_(bits) {
- set_representation(Representation::Integer32());
- SetFlag(kUseGVN);
- }
-
- bool IsDeletable() const override { return true; }
-
- Bits bits_;
-};
-
-
-class HConstructDouble final : public HTemplateInstruction<2> {
- public:
- DECLARE_INSTRUCTION_FACTORY_P2(HConstructDouble, HValue*, HValue*);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Integer32();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(ConstructDouble)
-
- HValue* hi() { return OperandAt(0); }
- HValue* lo() { return OperandAt(1); }
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- private:
- explicit HConstructDouble(HValue* hi, HValue* lo) {
- set_representation(Representation::Double());
- SetFlag(kUseGVN);
- SetOperandAt(0, hi);
- SetOperandAt(1, lo);
- }
-
- bool IsDeletable() const override { return true; }
-};
-
-
-enum RemovableSimulate {
- REMOVABLE_SIMULATE,
- FIXED_SIMULATE
-};
-
-
-class HSimulate final : public HInstruction {
- public:
- HSimulate(BailoutId ast_id, int pop_count, Zone* zone,
- RemovableSimulate removable)
- : ast_id_(ast_id),
- pop_count_(pop_count),
- values_(2, zone),
- assigned_indexes_(2, zone),
- zone_(zone),
- bit_field_(RemovableField::encode(removable) |
- DoneWithReplayField::encode(false)) {}
- ~HSimulate() {}
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- bool HasAstId() const { return !ast_id_.IsNone(); }
- BailoutId ast_id() const { return ast_id_; }
- void set_ast_id(BailoutId id) {
- DCHECK(!HasAstId());
- ast_id_ = id;
- }
-
- int pop_count() const { return pop_count_; }
- const ZoneList<HValue*>* values() const { return &values_; }
- int GetAssignedIndexAt(int index) const {
- DCHECK(HasAssignedIndexAt(index));
- return assigned_indexes_[index];
- }
- bool HasAssignedIndexAt(int index) const {
- return assigned_indexes_[index] != kNoIndex;
- }
- void AddAssignedValue(int index, HValue* value) {
- AddValue(index, value);
- }
- void AddPushedValue(HValue* value) {
- AddValue(kNoIndex, value);
- }
- int ToOperandIndex(int environment_index) {
- for (int i = 0; i < assigned_indexes_.length(); ++i) {
- if (assigned_indexes_[i] == environment_index) return i;
- }
- return -1;
- }
- int OperandCount() const override { return values_.length(); }
- HValue* OperandAt(int index) const override { return values_[index]; }
-
- bool HasEscapingOperandAt(int index) override { return false; }
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
-
- void MergeWith(ZoneList<HSimulate*>* list);
- bool is_candidate_for_removal() {
- return RemovableField::decode(bit_field_) == REMOVABLE_SIMULATE;
- }
-
- // Replay effects of this instruction on the given environment.
- void ReplayEnvironment(HEnvironment* env);
-
- DECLARE_CONCRETE_INSTRUCTION(Simulate)
-
-#ifdef DEBUG
- void Verify() override;
- void set_closure(Handle<JSFunction> closure) { closure_ = closure; }
- Handle<JSFunction> closure() const { return closure_; }
-#endif
-
- protected:
- void InternalSetOperandAt(int index, HValue* value) override {
- values_[index] = value;
- }
-
- private:
- static const int kNoIndex = -1;
- void AddValue(int index, HValue* value) {
- assigned_indexes_.Add(index, zone_);
- // Resize the list of pushed values.
- values_.Add(NULL, zone_);
- // Set the operand through the base method in HValue to make sure that the
- // use lists are correctly updated.
- SetOperandAt(values_.length() - 1, value);
- }
- bool HasValueForIndex(int index) {
- for (int i = 0; i < assigned_indexes_.length(); ++i) {
- if (assigned_indexes_[i] == index) return true;
- }
- return false;
- }
- bool is_done_with_replay() const {
- return DoneWithReplayField::decode(bit_field_);
- }
- void set_done_with_replay() {
- bit_field_ = DoneWithReplayField::update(bit_field_, true);
- }
-
- class RemovableField : public BitField<RemovableSimulate, 0, 1> {};
- class DoneWithReplayField : public BitField<bool, 1, 1> {};
-
- BailoutId ast_id_;
- int pop_count_;
- ZoneList<HValue*> values_;
- ZoneList<int> assigned_indexes_;
- Zone* zone_;
- uint32_t bit_field_;
-
-#ifdef DEBUG
- Handle<JSFunction> closure_;
-#endif
-};
-
-
-class HEnvironmentMarker final : public HTemplateInstruction<1> {
- public:
- enum Kind { BIND, LOOKUP };
-
- DECLARE_INSTRUCTION_FACTORY_P2(HEnvironmentMarker, Kind, int);
-
- Kind kind() const { return kind_; }
- int index() const { return index_; }
- HSimulate* next_simulate() { return next_simulate_; }
- void set_next_simulate(HSimulate* simulate) {
- next_simulate_ = simulate;
- }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
-#ifdef DEBUG
- void set_closure(Handle<JSFunction> closure) {
- DCHECK(closure_.is_null());
- DCHECK(!closure.is_null());
- closure_ = closure;
- }
- Handle<JSFunction> closure() const { return closure_; }
-#endif
-
- DECLARE_CONCRETE_INSTRUCTION(EnvironmentMarker);
-
- private:
- HEnvironmentMarker(Kind kind, int index)
- : kind_(kind), index_(index), next_simulate_(NULL) { }
-
- Kind kind_;
- int index_;
- HSimulate* next_simulate_;
-
-#ifdef DEBUG
- Handle<JSFunction> closure_;
-#endif
-};
-
-
-class HStackCheck final : public HTemplateInstruction<1> {
- public:
- enum Type {
- kFunctionEntry,
- kBackwardsBranch
- };
-
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HStackCheck, Type);
-
- HValue* context() { return OperandAt(0); }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- void Eliminate() {
- // The stack check eliminator might try to eliminate the same stack
- // check instruction multiple times.
- if (IsLinked()) {
- DeleteAndReplaceWith(NULL);
- }
- }
-
- bool is_function_entry() { return type_ == kFunctionEntry; }
- bool is_backwards_branch() { return type_ == kBackwardsBranch; }
-
- DECLARE_CONCRETE_INSTRUCTION(StackCheck)
-
- private:
- HStackCheck(HValue* context, Type type) : type_(type) {
- SetOperandAt(0, context);
- SetChangesFlag(kNewSpacePromotion);
- }
-
- Type type_;
-};
-
-
-enum InliningKind {
- NORMAL_RETURN, // Drop the function from the environment on return.
- CONSTRUCT_CALL_RETURN, // Either use allocated receiver or return value.
- GETTER_CALL_RETURN, // Returning from a getter, need to restore context.
- SETTER_CALL_RETURN // Use the RHS of the assignment as the return value.
-};
-
-
-class HArgumentsObject;
-class HConstant;
-
-
-class HEnterInlined final : public HTemplateInstruction<0> {
- public:
- static HEnterInlined* New(Isolate* isolate, Zone* zone, HValue* context,
- BailoutId return_id, Handle<JSFunction> closure,
- HConstant* closure_context, int arguments_count,
- FunctionLiteral* function,
- InliningKind inlining_kind, Variable* arguments_var,
- HArgumentsObject* arguments_object) {
- return new (zone) HEnterInlined(return_id, closure, closure_context,
- arguments_count, function, inlining_kind,
- arguments_var, arguments_object, zone);
- }
-
- void RegisterReturnTarget(HBasicBlock* return_target, Zone* zone);
- ZoneList<HBasicBlock*>* return_targets() { return &return_targets_; }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- Handle<SharedFunctionInfo> shared() const { return shared_; }
- Handle<JSFunction> closure() const { return closure_; }
- HConstant* closure_context() const { return closure_context_; }
- int arguments_count() const { return arguments_count_; }
- bool arguments_pushed() const { return arguments_pushed_; }
- void set_arguments_pushed() { arguments_pushed_ = true; }
- FunctionLiteral* function() const { return function_; }
- InliningKind inlining_kind() const { return inlining_kind_; }
- BailoutId ReturnId() const { return return_id_; }
- int inlining_id() const { return inlining_id_; }
- void set_inlining_id(int inlining_id) { inlining_id_ = inlining_id; }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
-
- Variable* arguments_var() { return arguments_var_; }
- HArgumentsObject* arguments_object() { return arguments_object_; }
-
- DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
-
- private:
- HEnterInlined(BailoutId return_id, Handle<JSFunction> closure,
- HConstant* closure_context, int arguments_count,
- FunctionLiteral* function, InliningKind inlining_kind,
- Variable* arguments_var, HArgumentsObject* arguments_object,
- Zone* zone)
- : return_id_(return_id),
- shared_(handle(closure->shared())),
- closure_(closure),
- closure_context_(closure_context),
- arguments_count_(arguments_count),
- arguments_pushed_(false),
- function_(function),
- inlining_kind_(inlining_kind),
- inlining_id_(0),
- arguments_var_(arguments_var),
- arguments_object_(arguments_object),
- return_targets_(2, zone) {}
-
- BailoutId return_id_;
- Handle<SharedFunctionInfo> shared_;
- Handle<JSFunction> closure_;
- HConstant* closure_context_;
- int arguments_count_;
- bool arguments_pushed_;
- FunctionLiteral* function_;
- InliningKind inlining_kind_;
- int inlining_id_;
- Variable* arguments_var_;
- HArgumentsObject* arguments_object_;
- ZoneList<HBasicBlock*> return_targets_;
-};
-
-
-class HLeaveInlined final : public HTemplateInstruction<0> {
- public:
- HLeaveInlined(HEnterInlined* entry,
- int drop_count)
- : entry_(entry),
- drop_count_(drop_count) { }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
-
- int argument_delta() const override {
- return entry_->arguments_pushed() ? -drop_count_ : 0;
- }
-
- DECLARE_CONCRETE_INSTRUCTION(LeaveInlined)
-
- private:
- HEnterInlined* entry_;
- int drop_count_;
-};
-
-
-class HPushArguments final : public HInstruction {
- public:
- static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context) {
- return new(zone) HPushArguments(zone);
- }
- static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* arg1) {
- HPushArguments* instr = new(zone) HPushArguments(zone);
- instr->AddInput(arg1);
- return instr;
- }
- static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* arg1, HValue* arg2) {
- HPushArguments* instr = new(zone) HPushArguments(zone);
- instr->AddInput(arg1);
- instr->AddInput(arg2);
- return instr;
- }
- static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* arg1, HValue* arg2, HValue* arg3) {
- HPushArguments* instr = new(zone) HPushArguments(zone);
- instr->AddInput(arg1);
- instr->AddInput(arg2);
- instr->AddInput(arg3);
- return instr;
- }
- static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* arg1, HValue* arg2, HValue* arg3,
- HValue* arg4) {
- HPushArguments* instr = new(zone) HPushArguments(zone);
- instr->AddInput(arg1);
- instr->AddInput(arg2);
- instr->AddInput(arg3);
- instr->AddInput(arg4);
- return instr;
- }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- int argument_delta() const override { return inputs_.length(); }
- HValue* argument(int i) { return OperandAt(i); }
-
- int OperandCount() const final { return inputs_.length(); }
- HValue* OperandAt(int i) const final { return inputs_[i]; }
-
- void AddInput(HValue* value);
-
- DECLARE_CONCRETE_INSTRUCTION(PushArguments)
-
- protected:
- void InternalSetOperandAt(int i, HValue* value) final { inputs_[i] = value; }
-
- private:
- explicit HPushArguments(Zone* zone)
- : HInstruction(HType::Tagged()), inputs_(4, zone) {
- set_representation(Representation::Tagged());
- }
-
- ZoneList<HValue*> inputs_;
-};
-
-
-class HThisFunction final : public HTemplateInstruction<0> {
- public:
- DECLARE_INSTRUCTION_FACTORY_P0(HThisFunction);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(ThisFunction)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- private:
- HThisFunction() {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- }
-
- bool IsDeletable() const override { return true; }
-};
-
-
-class HDeclareGlobals final : public HUnaryOperation {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HDeclareGlobals,
- Handle<FixedArray>,
- int);
-
- HValue* context() { return OperandAt(0); }
- Handle<FixedArray> pairs() const { return pairs_; }
- int flags() const { return flags_; }
-
- DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals)
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- private:
- HDeclareGlobals(HValue* context,
- Handle<FixedArray> pairs,
- int flags)
- : HUnaryOperation(context),
- pairs_(pairs),
- flags_(flags) {
- set_representation(Representation::Tagged());
- SetAllSideEffects();
- }
-
- Handle<FixedArray> pairs_;
- int flags_;
-};
-
-
-template <int V>
-class HCall : public HTemplateInstruction<V> {
- public:
- // The argument count includes the receiver.
- explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
- this->set_representation(Representation::Tagged());
- this->SetAllSideEffects();
- }
-
- HType CalculateInferredType() final { return HType::Tagged(); }
-
- virtual int argument_count() const {
- return argument_count_;
- }
-
- int argument_delta() const override { return -argument_count(); }
-
- private:
- int argument_count_;
-};
-
-
-class HUnaryCall : public HCall<1> {
- public:
- HUnaryCall(HValue* value, int argument_count)
- : HCall<1>(argument_count) {
- SetOperandAt(0, value);
- }
-
- Representation RequiredInputRepresentation(int index) final {
- return Representation::Tagged();
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- HValue* value() const { return OperandAt(0); }
-};
-
-
-class HBinaryCall : public HCall<2> {
- public:
- HBinaryCall(HValue* first, HValue* second, int argument_count)
- : HCall<2>(argument_count) {
- SetOperandAt(0, first);
- SetOperandAt(1, second);
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- Representation RequiredInputRepresentation(int index) final {
- return Representation::Tagged();
- }
-
- HValue* first() const { return OperandAt(0); }
- HValue* second() const { return OperandAt(1); }
-};
-
-
-class HCallJSFunction final : public HCall<1> {
- public:
- static HCallJSFunction* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* function, int argument_count);
-
- HValue* function() const { return OperandAt(0); }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- Representation RequiredInputRepresentation(int index) final {
- DCHECK(index == 0);
- return Representation::Tagged();
- }
-
- bool HasStackCheck() final { return has_stack_check_; }
-
- DECLARE_CONCRETE_INSTRUCTION(CallJSFunction)
-
- private:
- // The argument count includes the receiver.
- HCallJSFunction(HValue* function,
- int argument_count,
- bool has_stack_check)
- : HCall<1>(argument_count),
- has_stack_check_(has_stack_check) {
- SetOperandAt(0, function);
- }
-
- bool has_stack_check_;
-};
-
-
-enum CallMode { NORMAL_CALL, TAIL_CALL };
-
-
-class HCallWithDescriptor final : public HInstruction {
- public:
- static HCallWithDescriptor* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* target, int argument_count,
- CallInterfaceDescriptor descriptor,
- const Vector<HValue*>& operands,
- CallMode call_mode = NORMAL_CALL) {
- HCallWithDescriptor* res = new (zone) HCallWithDescriptor(
- target, argument_count, descriptor, operands, call_mode, zone);
- DCHECK(operands.length() == res->GetParameterCount());
- return res;
- }
-
- int OperandCount() const final { return values_.length(); }
- HValue* OperandAt(int index) const final { return values_[index]; }
-
- Representation RequiredInputRepresentation(int index) final {
- if (index == 0 || index == 1) {
- // Target + context
- return Representation::Tagged();
- } else {
- int par_index = index - 2;
- DCHECK(par_index < GetParameterCount());
- return RepresentationFromType(descriptor_.GetParameterType(par_index));
- }
- }
-
- DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor)
-
- HType CalculateInferredType() final { return HType::Tagged(); }
-
- bool IsTailCall() const { return call_mode_ == TAIL_CALL; }
-
- virtual int argument_count() const {
- return argument_count_;
- }
-
- int argument_delta() const override { return -argument_count_; }
-
- CallInterfaceDescriptor descriptor() const { return descriptor_; }
-
- HValue* target() {
- return OperandAt(0);
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- private:
- // The argument count includes the receiver.
- HCallWithDescriptor(HValue* target, int argument_count,
- CallInterfaceDescriptor descriptor,
- const Vector<HValue*>& operands, CallMode call_mode,
- Zone* zone)
- : descriptor_(descriptor),
- values_(GetParameterCount() + 1, zone),
- argument_count_(argument_count),
- call_mode_(call_mode) {
- // We can only tail call without any stack arguments.
- DCHECK(call_mode != TAIL_CALL || argument_count == 0);
- AddOperand(target, zone);
- for (int i = 0; i < operands.length(); i++) {
- AddOperand(operands[i], zone);
- }
- this->set_representation(Representation::Tagged());
- this->SetAllSideEffects();
- }
-
- void AddOperand(HValue* v, Zone* zone) {
- values_.Add(NULL, zone);
- SetOperandAt(values_.length() - 1, v);
- }
-
- int GetParameterCount() const {
- return descriptor_.GetRegisterParameterCount() + 1;
- }
-
- void InternalSetOperandAt(int index, HValue* value) final {
- values_[index] = value;
- }
-
- CallInterfaceDescriptor descriptor_;
- ZoneList<HValue*> values_;
- int argument_count_;
- CallMode call_mode_;
-};
-
-
-class HInvokeFunction final : public HBinaryCall {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInvokeFunction, HValue*, int);
-
- HInvokeFunction(HValue* context,
- HValue* function,
- Handle<JSFunction> known_function,
- int argument_count)
- : HBinaryCall(context, function, argument_count),
- known_function_(known_function) {
- formal_parameter_count_ =
- known_function.is_null()
- ? 0
- : known_function->shared()->internal_formal_parameter_count();
- has_stack_check_ = !known_function.is_null() &&
- (known_function->code()->kind() == Code::FUNCTION ||
- known_function->code()->kind() == Code::OPTIMIZED_FUNCTION);
- }
-
- static HInvokeFunction* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* function,
- Handle<JSFunction> known_function,
- int argument_count) {
- return new(zone) HInvokeFunction(context, function,
- known_function, argument_count);
- }
-
- HValue* context() { return first(); }
- HValue* function() { return second(); }
- Handle<JSFunction> known_function() { return known_function_; }
- int formal_parameter_count() const { return formal_parameter_count_; }
-
- bool HasStackCheck() final { return has_stack_check_; }
-
- DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
-
- private:
- HInvokeFunction(HValue* context, HValue* function, int argument_count)
- : HBinaryCall(context, function, argument_count),
- has_stack_check_(false) {
- }
-
- Handle<JSFunction> known_function_;
- int formal_parameter_count_;
- bool has_stack_check_;
-};
-
-
-class HCallFunction final : public HBinaryCall {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallFunction, HValue*, int);
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(
- HCallFunction, HValue*, int, CallFunctionFlags);
-
- HValue* context() const { return first(); }
- HValue* function() const { return second(); }
- CallFunctionFlags function_flags() const { return function_flags_; }
-
- FeedbackVectorSlot slot() const { return slot_; }
- Handle<TypeFeedbackVector> feedback_vector() const {
- return feedback_vector_;
- }
- bool HasVectorAndSlot() const { return !feedback_vector_.is_null(); }
- void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
- FeedbackVectorSlot slot) {
- feedback_vector_ = vector;
- slot_ = slot;
- }
-
- DECLARE_CONCRETE_INSTRUCTION(CallFunction)
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- int argument_delta() const override { return -argument_count(); }
-
- private:
- HCallFunction(HValue* context, HValue* function, int argument_count,
- CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS)
- : HBinaryCall(context, function, argument_count),
- function_flags_(flags) {}
- CallFunctionFlags function_flags_;
- Handle<TypeFeedbackVector> feedback_vector_;
- FeedbackVectorSlot slot_;
-};
-
-
-class HCallNew final : public HBinaryCall {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallNew, HValue*, int);
-
- HValue* context() { return first(); }
- HValue* constructor() { return second(); }
-
- DECLARE_CONCRETE_INSTRUCTION(CallNew)
-
- private:
- HCallNew(HValue* context, HValue* constructor, int argument_count)
- : HBinaryCall(context, constructor, argument_count) {}
-};
-
-
-class HCallNewArray final : public HBinaryCall {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HCallNewArray, HValue*, int,
- ElementsKind,
- Handle<AllocationSite>);
-
- HValue* context() { return first(); }
- HValue* constructor() { return second(); }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- ElementsKind elements_kind() const { return elements_kind_; }
- Handle<AllocationSite> site() const { return site_; }
-
- DECLARE_CONCRETE_INSTRUCTION(CallNewArray)
-
- private:
- HCallNewArray(HValue* context, HValue* constructor, int argument_count,
- ElementsKind elements_kind, Handle<AllocationSite> site)
- : HBinaryCall(context, constructor, argument_count),
- elements_kind_(elements_kind),
- site_(site) {}
-
- ElementsKind elements_kind_;
- Handle<AllocationSite> site_;
-};
-
-
-class HCallRuntime final : public HCall<1> {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallRuntime,
- const Runtime::Function*, int);
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- HValue* context() { return OperandAt(0); }
- const Runtime::Function* function() const { return c_function_; }
- SaveFPRegsMode save_doubles() const { return save_doubles_; }
- void set_save_doubles(SaveFPRegsMode save_doubles) {
- save_doubles_ = save_doubles;
- }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(CallRuntime)
-
- private:
- HCallRuntime(HValue* context, const Runtime::Function* c_function,
- int argument_count)
- : HCall<1>(argument_count),
- c_function_(c_function),
- save_doubles_(kDontSaveFPRegs) {
- SetOperandAt(0, context);
- }
-
- const Runtime::Function* c_function_;
- SaveFPRegsMode save_doubles_;
-};
-
-
-class HMapEnumLength final : public HUnaryOperation {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HMapEnumLength, HValue*);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(MapEnumLength)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- private:
- explicit HMapEnumLength(HValue* value)
- : HUnaryOperation(value, HType::Smi()) {
- set_representation(Representation::Smi());
- SetFlag(kUseGVN);
- SetDependsOnFlag(kMaps);
- }
-
- bool IsDeletable() const override { return true; }
-};
-
-
-class HUnaryMathOperation final : public HTemplateInstruction<2> {
- public:
- static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* value, BuiltinFunctionId op);
-
- HValue* context() const { return OperandAt(0); }
- HValue* value() const { return OperandAt(1); }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- Representation RequiredInputRepresentation(int index) override {
- if (index == 0) {
- return Representation::Tagged();
- } else {
- switch (op_) {
- case kMathFloor:
- case kMathRound:
- case kMathFround:
- case kMathSqrt:
- case kMathPowHalf:
- case kMathLog:
- case kMathExp:
- return Representation::Double();
- case kMathAbs:
- return representation();
- case kMathClz32:
- return Representation::Integer32();
- default:
- UNREACHABLE();
- return Representation::None();
- }
- }
- }
-
- Range* InferRange(Zone* zone) override;
-
- HValue* Canonicalize() override;
- Representation RepresentationFromUses() override;
- Representation RepresentationFromInputs() override;
-
- BuiltinFunctionId op() const { return op_; }
- const char* OpName() const;
-
- DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)
-
- protected:
- bool DataEquals(HValue* other) override {
- HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
- return op_ == b->op();
- }
-
- private:
- // Indicates if we support a double (and int32) output for Math.floor and
- // Math.round.
- bool SupportsFlexibleFloorAndRound() const {
-#ifdef V8_TARGET_ARCH_ARM64
- // TODO(rmcilroy): Re-enable this for Arm64 once http://crbug.com/476477 is
- // fixed.
- return false;
-#else
- return false;
-#endif
- }
- HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
- : HTemplateInstruction<2>(HType::TaggedNumber()), op_(op) {
- SetOperandAt(0, context);
- SetOperandAt(1, value);
- switch (op) {
- case kMathFloor:
- case kMathRound:
- if (SupportsFlexibleFloorAndRound()) {
- SetFlag(kFlexibleRepresentation);
- } else {
- set_representation(Representation::Integer32());
- }
- break;
- case kMathClz32:
- set_representation(Representation::Integer32());
- break;
- case kMathAbs:
- // Not setting representation here: it is None intentionally.
- SetFlag(kFlexibleRepresentation);
- // TODO(svenpanne) This flag is actually only needed if representation()
- // is tagged, and not when it is an unboxed double or unboxed integer.
- SetChangesFlag(kNewSpacePromotion);
- break;
- case kMathFround:
- case kMathLog:
- case kMathExp:
- case kMathSqrt:
- case kMathPowHalf:
- set_representation(Representation::Double());
- break;
- default:
- UNREACHABLE();
- }
- SetFlag(kUseGVN);
- SetFlag(kAllowUndefinedAsNaN);
- }
-
- bool IsDeletable() const override {
- // TODO(crankshaft): This should be true, however the semantics of this
- // instruction also include the ToNumber conversion that is mentioned in the
- // spec, which is of course observable.
- return false;
- }
-
- HValue* SimplifiedDividendForMathFloorOfDiv(HDiv* hdiv);
- HValue* SimplifiedDivisorForMathFloorOfDiv(HDiv* hdiv);
-
- BuiltinFunctionId op_;
-};
-
-
-class HLoadRoot final : public HTemplateInstruction<0> {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HLoadRoot, Heap::RootListIndex);
- DECLARE_INSTRUCTION_FACTORY_P2(HLoadRoot, Heap::RootListIndex, HType);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
-
- Heap::RootListIndex index() const { return index_; }
-
- DECLARE_CONCRETE_INSTRUCTION(LoadRoot)
-
- protected:
- bool DataEquals(HValue* other) override {
- HLoadRoot* b = HLoadRoot::cast(other);
- return index_ == b->index_;
- }
-
- private:
- explicit HLoadRoot(Heap::RootListIndex index, HType type = HType::Tagged())
- : HTemplateInstruction<0>(type), index_(index) {
- SetFlag(kUseGVN);
- // TODO(bmeurer): We'll need kDependsOnRoots once we add the
- // corresponding HStoreRoot instruction.
- SetDependsOnFlag(kCalls);
- set_representation(Representation::Tagged());
- }
-
- bool IsDeletable() const override { return true; }
-
- const Heap::RootListIndex index_;
-};
-
-
-class HCheckMaps final : public HTemplateInstruction<2> {
- public:
- static HCheckMaps* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* value, Handle<Map> map,
- HValue* typecheck = NULL) {
- return new(zone) HCheckMaps(value, new(zone) UniqueSet<Map>(
- Unique<Map>::CreateImmovable(map), zone), typecheck);
- }
- static HCheckMaps* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* value, SmallMapList* map_list,
- HValue* typecheck = NULL) {
- UniqueSet<Map>* maps = new(zone) UniqueSet<Map>(map_list->length(), zone);
- for (int i = 0; i < map_list->length(); ++i) {
- maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone);
- }
- return new(zone) HCheckMaps(value, maps, typecheck);
- }
-
- bool IsStabilityCheck() const {
- return IsStabilityCheckField::decode(bit_field_);
- }
- void MarkAsStabilityCheck() {
- bit_field_ = MapsAreStableField::encode(true) |
- HasMigrationTargetField::encode(false) |
- IsStabilityCheckField::encode(true);
- ClearChangesFlag(kNewSpacePromotion);
- ClearDependsOnFlag(kElementsKind);
- ClearDependsOnFlag(kMaps);
- }
-
- bool HasEscapingOperandAt(int index) override { return false; }
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- HType CalculateInferredType() override {
- if (value()->type().IsHeapObject()) return value()->type();
- return HType::HeapObject();
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- HValue* value() const { return OperandAt(0); }
- HValue* typecheck() const { return OperandAt(1); }
-
- const UniqueSet<Map>* maps() const { return maps_; }
- void set_maps(const UniqueSet<Map>* maps) { maps_ = maps; }
-
- bool maps_are_stable() const {
- return MapsAreStableField::decode(bit_field_);
- }
-
- bool HasMigrationTarget() const {
- return HasMigrationTargetField::decode(bit_field_);
- }
-
- HValue* Canonicalize() override;
-
- static HCheckMaps* CreateAndInsertAfter(Zone* zone,
- HValue* value,
- Unique<Map> map,
- bool map_is_stable,
- HInstruction* instr) {
- return instr->Append(new(zone) HCheckMaps(
- value, new(zone) UniqueSet<Map>(map, zone), map_is_stable));
- }
-
- static HCheckMaps* CreateAndInsertBefore(Zone* zone,
- HValue* value,
- const UniqueSet<Map>* maps,
- bool maps_are_stable,
- HInstruction* instr) {
- return instr->Prepend(new(zone) HCheckMaps(value, maps, maps_are_stable));
- }
-
- DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
-
- protected:
- bool DataEquals(HValue* other) override {
- return this->maps()->Equals(HCheckMaps::cast(other)->maps());
- }
-
- int RedefinedOperandIndex() override { return 0; }
-
- private:
- HCheckMaps(HValue* value, const UniqueSet<Map>* maps, bool maps_are_stable)
- : HTemplateInstruction<2>(HType::HeapObject()),
- maps_(maps),
- bit_field_(HasMigrationTargetField::encode(false) |
- IsStabilityCheckField::encode(false) |
- MapsAreStableField::encode(maps_are_stable)) {
- DCHECK_NE(0, maps->size());
- SetOperandAt(0, value);
- // Use the object value for the dependency.
- SetOperandAt(1, value);
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetDependsOnFlag(kMaps);
- SetDependsOnFlag(kElementsKind);
- }
-
- HCheckMaps(HValue* value, const UniqueSet<Map>* maps, HValue* typecheck)
- : HTemplateInstruction<2>(HType::HeapObject()),
- maps_(maps),
- bit_field_(HasMigrationTargetField::encode(false) |
- IsStabilityCheckField::encode(false) |
- MapsAreStableField::encode(true)) {
- DCHECK_NE(0, maps->size());
- SetOperandAt(0, value);
- // Use the object value for the dependency if NULL is passed.
- SetOperandAt(1, typecheck ? typecheck : value);
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetDependsOnFlag(kMaps);
- SetDependsOnFlag(kElementsKind);
- for (int i = 0; i < maps->size(); ++i) {
- Handle<Map> map = maps->at(i).handle();
- if (map->is_migration_target()) {
- bit_field_ = HasMigrationTargetField::update(bit_field_, true);
- }
- if (!map->is_stable()) {
- bit_field_ = MapsAreStableField::update(bit_field_, false);
- }
- }
- if (HasMigrationTarget()) SetChangesFlag(kNewSpacePromotion);
- }
-
- class HasMigrationTargetField : public BitField<bool, 0, 1> {};
- class IsStabilityCheckField : public BitField<bool, 1, 1> {};
- class MapsAreStableField : public BitField<bool, 2, 1> {};
-
- const UniqueSet<Map>* maps_;
- uint32_t bit_field_;
-};
-
-
-class HCheckValue final : public HUnaryOperation {
- public:
- static HCheckValue* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* value, Handle<JSFunction> func) {
- bool in_new_space = isolate->heap()->InNewSpace(*func);
- // NOTE: We create an uninitialized Unique and initialize it later.
- // This is because a JSFunction can move due to GC during graph creation.
- // TODO(titzer): This is a migration crutch. Replace with some kind of
- // Uniqueness scope later.
- Unique<JSFunction> target = Unique<JSFunction>::CreateUninitialized(func);
- HCheckValue* check = new(zone) HCheckValue(value, target, in_new_space);
- return check;
- }
- static HCheckValue* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* value, Unique<HeapObject> target,
- bool object_in_new_space) {
- return new(zone) HCheckValue(value, target, object_in_new_space);
- }
-
- void FinalizeUniqueness() override {
- object_ = Unique<HeapObject>(object_.handle());
- }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- HValue* Canonicalize() override;
-
-#ifdef DEBUG
- void Verify() override;
-#endif
-
- Unique<HeapObject> object() const { return object_; }
- bool object_in_new_space() const { return object_in_new_space_; }
-
- DECLARE_CONCRETE_INSTRUCTION(CheckValue)
-
- protected:
- bool DataEquals(HValue* other) override {
- HCheckValue* b = HCheckValue::cast(other);
- return object_ == b->object_;
- }
-
- private:
- HCheckValue(HValue* value, Unique<HeapObject> object,
- bool object_in_new_space)
- : HUnaryOperation(value, value->type()),
- object_(object),
- object_in_new_space_(object_in_new_space) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- }
-
- Unique<HeapObject> object_;
- bool object_in_new_space_;
-};
-
-
-class HCheckInstanceType final : public HUnaryOperation {
- public:
- enum Check {
- IS_SPEC_OBJECT,
- IS_JS_ARRAY,
- IS_JS_DATE,
- IS_STRING,
- IS_INTERNALIZED_STRING,
- LAST_INTERVAL_CHECK = IS_JS_DATE
- };
-
- DECLARE_INSTRUCTION_FACTORY_P2(HCheckInstanceType, HValue*, Check);
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- HType CalculateInferredType() override {
- switch (check_) {
- case IS_SPEC_OBJECT: return HType::JSObject();
- case IS_JS_ARRAY: return HType::JSArray();
- case IS_JS_DATE:
- return HType::JSObject();
- case IS_STRING: return HType::String();
- case IS_INTERNALIZED_STRING: return HType::String();
- }
- UNREACHABLE();
- return HType::Tagged();
- }
-
- HValue* Canonicalize() override;
-
- bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
- void GetCheckInterval(InstanceType* first, InstanceType* last);
- void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);
-
- Check check() const { return check_; }
-
- DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)
-
- protected:
- // TODO(ager): It could be nice to allow the ommision of instance
- // type checks if we have already performed an instance type check
- // with a larger range.
- bool DataEquals(HValue* other) override {
- HCheckInstanceType* b = HCheckInstanceType::cast(other);
- return check_ == b->check_;
- }
-
- int RedefinedOperandIndex() override { return 0; }
-
- private:
- const char* GetCheckName() const;
-
- HCheckInstanceType(HValue* value, Check check)
- : HUnaryOperation(value, HType::HeapObject()), check_(check) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- }
-
- const Check check_;
-};
-
-
-class HCheckSmi final : public HUnaryOperation {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HCheckSmi, HValue*);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- HValue* Canonicalize() override {
- HType value_type = value()->type();
- if (value_type.IsSmi()) {
- return NULL;
- }
- return this;
- }
-
- DECLARE_CONCRETE_INSTRUCTION(CheckSmi)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- private:
- explicit HCheckSmi(HValue* value) : HUnaryOperation(value, HType::Smi()) {
- set_representation(Representation::Smi());
- SetFlag(kUseGVN);
- }
-};
-
-
-class HCheckArrayBufferNotNeutered final : public HUnaryOperation {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HCheckArrayBufferNotNeutered, HValue*);
-
- bool HasEscapingOperandAt(int index) override { return false; }
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- HType CalculateInferredType() override {
- if (value()->type().IsHeapObject()) return value()->type();
- return HType::HeapObject();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
- int RedefinedOperandIndex() override { return 0; }
-
- private:
- explicit HCheckArrayBufferNotNeutered(HValue* value)
- : HUnaryOperation(value) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetDependsOnFlag(kCalls);
- }
-};
-
-
-class HCheckHeapObject final : public HUnaryOperation {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HCheckHeapObject, HValue*);
-
- bool HasEscapingOperandAt(int index) override { return false; }
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- HType CalculateInferredType() override {
- if (value()->type().IsHeapObject()) return value()->type();
- return HType::HeapObject();
- }
-
-#ifdef DEBUG
- void Verify() override;
-#endif
-
- HValue* Canonicalize() override {
- return value()->type().IsHeapObject() ? NULL : this;
- }
-
- DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- private:
- explicit HCheckHeapObject(HValue* value) : HUnaryOperation(value) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- }
-};
-
-
-class InductionVariableData;
-
-
-struct InductionVariableLimitUpdate {
- InductionVariableData* updated_variable;
- HValue* limit;
- bool limit_is_upper;
- bool limit_is_included;
-
- InductionVariableLimitUpdate()
- : updated_variable(NULL), limit(NULL),
- limit_is_upper(false), limit_is_included(false) {}
-};
-
-
-class HBoundsCheck;
-class HPhi;
-class HBitwise;
-
-
-class InductionVariableData final : public ZoneObject {
- public:
- class InductionVariableCheck : public ZoneObject {
- public:
- HBoundsCheck* check() { return check_; }
- InductionVariableCheck* next() { return next_; }
- bool HasUpperLimit() { return upper_limit_ >= 0; }
- int32_t upper_limit() {
- DCHECK(HasUpperLimit());
- return upper_limit_;
- }
- void set_upper_limit(int32_t upper_limit) {
- upper_limit_ = upper_limit;
- }
-
- bool processed() { return processed_; }
- void set_processed() { processed_ = true; }
-
- InductionVariableCheck(HBoundsCheck* check,
- InductionVariableCheck* next,
- int32_t upper_limit = kNoLimit)
- : check_(check), next_(next), upper_limit_(upper_limit),
- processed_(false) {}
-
- private:
- HBoundsCheck* check_;
- InductionVariableCheck* next_;
- int32_t upper_limit_;
- bool processed_;
- };
-
- class ChecksRelatedToLength : public ZoneObject {
- public:
- HValue* length() { return length_; }
- ChecksRelatedToLength* next() { return next_; }
- InductionVariableCheck* checks() { return checks_; }
-
- void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
- void CloseCurrentBlock();
-
- ChecksRelatedToLength(HValue* length, ChecksRelatedToLength* next)
- : length_(length), next_(next), checks_(NULL),
- first_check_in_block_(NULL),
- added_index_(NULL),
- added_constant_(NULL),
- current_and_mask_in_block_(0),
- current_or_mask_in_block_(0) {}
-
- private:
- void UseNewIndexInCurrentBlock(Token::Value token,
- int32_t mask,
- HValue* index_base,
- HValue* context);
-
- HBoundsCheck* first_check_in_block() { return first_check_in_block_; }
- HBitwise* added_index() { return added_index_; }
- void set_added_index(HBitwise* index) { added_index_ = index; }
- HConstant* added_constant() { return added_constant_; }
- void set_added_constant(HConstant* constant) { added_constant_ = constant; }
- int32_t current_and_mask_in_block() { return current_and_mask_in_block_; }
- int32_t current_or_mask_in_block() { return current_or_mask_in_block_; }
- int32_t current_upper_limit() { return current_upper_limit_; }
-
- HValue* length_;
- ChecksRelatedToLength* next_;
- InductionVariableCheck* checks_;
-
- HBoundsCheck* first_check_in_block_;
- HBitwise* added_index_;
- HConstant* added_constant_;
- int32_t current_and_mask_in_block_;
- int32_t current_or_mask_in_block_;
- int32_t current_upper_limit_;
- };
-
- struct LimitFromPredecessorBlock {
- InductionVariableData* variable;
- Token::Value token;
- HValue* limit;
- HBasicBlock* other_target;
-
- bool LimitIsValid() { return token != Token::ILLEGAL; }
-
- bool LimitIsIncluded() {
- return Token::IsEqualityOp(token) ||
- token == Token::GTE || token == Token::LTE;
- }
- bool LimitIsUpper() {
- return token == Token::LTE || token == Token::LT || token == Token::NE;
- }
-
- LimitFromPredecessorBlock()
- : variable(NULL),
- token(Token::ILLEGAL),
- limit(NULL),
- other_target(NULL) {}
- };
-
- static const int32_t kNoLimit = -1;
-
- static InductionVariableData* ExaminePhi(HPhi* phi);
- static void ComputeLimitFromPredecessorBlock(
- HBasicBlock* block,
- LimitFromPredecessorBlock* result);
- static bool ComputeInductionVariableLimit(
- HBasicBlock* block,
- InductionVariableLimitUpdate* additional_limit);
-
- struct BitwiseDecompositionResult {
- HValue* base;
- int32_t and_mask;
- int32_t or_mask;
- HValue* context;
-
- BitwiseDecompositionResult()
- : base(NULL), and_mask(0), or_mask(0), context(NULL) {}
- };
- static void DecomposeBitwise(HValue* value,
- BitwiseDecompositionResult* result);
-
- void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
-
- bool CheckIfBranchIsLoopGuard(Token::Value token,
- HBasicBlock* current_branch,
- HBasicBlock* other_branch);
-
- void UpdateAdditionalLimit(InductionVariableLimitUpdate* update);
-
- HPhi* phi() { return phi_; }
- HValue* base() { return base_; }
- int32_t increment() { return increment_; }
- HValue* limit() { return limit_; }
- bool limit_included() { return limit_included_; }
- HBasicBlock* limit_validity() { return limit_validity_; }
- HBasicBlock* induction_exit_block() { return induction_exit_block_; }
- HBasicBlock* induction_exit_target() { return induction_exit_target_; }
- ChecksRelatedToLength* checks() { return checks_; }
- HValue* additional_upper_limit() { return additional_upper_limit_; }
- bool additional_upper_limit_is_included() {
- return additional_upper_limit_is_included_;
- }
- HValue* additional_lower_limit() { return additional_lower_limit_; }
- bool additional_lower_limit_is_included() {
- return additional_lower_limit_is_included_;
- }
-
- bool LowerLimitIsNonNegativeConstant() {
- if (base()->IsInteger32Constant() && base()->GetInteger32Constant() >= 0) {
- return true;
- }
- if (additional_lower_limit() != NULL &&
- additional_lower_limit()->IsInteger32Constant() &&
- additional_lower_limit()->GetInteger32Constant() >= 0) {
- // Ignoring the corner case of !additional_lower_limit_is_included()
- // is safe, handling it adds unneeded complexity.
- return true;
- }
- return false;
- }
-
- int32_t ComputeUpperLimit(int32_t and_mask, int32_t or_mask);
-
- private:
- template <class T> void swap(T* a, T* b) {
- T c(*a);
- *a = *b;
- *b = c;
- }
-
- InductionVariableData(HPhi* phi, HValue* base, int32_t increment)
- : phi_(phi), base_(IgnoreOsrValue(base)), increment_(increment),
- limit_(NULL), limit_included_(false), limit_validity_(NULL),
- induction_exit_block_(NULL), induction_exit_target_(NULL),
- checks_(NULL),
- additional_upper_limit_(NULL),
- additional_upper_limit_is_included_(false),
- additional_lower_limit_(NULL),
- additional_lower_limit_is_included_(false) {}
-
- static int32_t ComputeIncrement(HPhi* phi, HValue* phi_operand);
-
- static HValue* IgnoreOsrValue(HValue* v);
- static InductionVariableData* GetInductionVariableData(HValue* v);
-
- HPhi* phi_;
- HValue* base_;
- int32_t increment_;
- HValue* limit_;
- bool limit_included_;
- HBasicBlock* limit_validity_;
- HBasicBlock* induction_exit_block_;
- HBasicBlock* induction_exit_target_;
- ChecksRelatedToLength* checks_;
- HValue* additional_upper_limit_;
- bool additional_upper_limit_is_included_;
- HValue* additional_lower_limit_;
- bool additional_lower_limit_is_included_;
-};
-
-
-class HPhi final : public HValue {
- public:
- HPhi(int merged_index, Zone* zone)
- : inputs_(2, zone), merged_index_(merged_index) {
- DCHECK(merged_index >= 0 || merged_index == kInvalidMergedIndex);
- SetFlag(kFlexibleRepresentation);
- SetFlag(kAllowUndefinedAsNaN);
- }
-
- Representation RepresentationFromInputs() override;
-
- Range* InferRange(Zone* zone) override;
- virtual void InferRepresentation(HInferRepresentationPhase* h_infer) override;
- Representation RequiredInputRepresentation(int index) override {
- return representation();
- }
- Representation KnownOptimalRepresentation() override {
- return representation();
- }
- HType CalculateInferredType() override;
- int OperandCount() const override { return inputs_.length(); }
- HValue* OperandAt(int index) const override { return inputs_[index]; }
- HValue* GetRedundantReplacement();
- void AddInput(HValue* value);
- bool HasRealUses();
-
- bool IsReceiver() const { return merged_index_ == 0; }
- bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; }
-
- SourcePosition position() const override;
-
- int merged_index() const { return merged_index_; }
-
- InductionVariableData* induction_variable_data() {
- return induction_variable_data_;
- }
- bool IsInductionVariable() {
- return induction_variable_data_ != NULL;
- }
- bool IsLimitedInductionVariable() {
- return IsInductionVariable() &&
- induction_variable_data_->limit() != NULL;
- }
- void DetectInductionVariable() {
- DCHECK(induction_variable_data_ == NULL);
- induction_variable_data_ = InductionVariableData::ExaminePhi(this);
- }
-
- std::ostream& PrintTo(std::ostream& os) const override; // NOLINT
-
-#ifdef DEBUG
- void Verify() override;
-#endif
-
- void InitRealUses(int id);
- void AddNonPhiUsesFrom(HPhi* other);
-
- Representation representation_from_indirect_uses() const {
- return representation_from_indirect_uses_;
- }
-
- bool has_type_feedback_from_uses() const {
- return has_type_feedback_from_uses_;
- }
-
- int phi_id() { return phi_id_; }
-
- static HPhi* cast(HValue* value) {
- DCHECK(value->IsPhi());
- return reinterpret_cast<HPhi*>(value);
- }
- Opcode opcode() const override { return HValue::kPhi; }
-
- void SimplifyConstantInputs();
-
- // Marker value representing an invalid merge index.
- static const int kInvalidMergedIndex = -1;
-
- protected:
- void DeleteFromGraph() override;
- void InternalSetOperandAt(int index, HValue* value) override {
- inputs_[index] = value;
- }
-
- private:
- Representation representation_from_non_phi_uses() const {
- return representation_from_non_phi_uses_;
- }
-
- ZoneList<HValue*> inputs_;
- int merged_index_ = 0;
-
- int phi_id_ = -1;
- InductionVariableData* induction_variable_data_ = nullptr;
-
- Representation representation_from_indirect_uses_ = Representation::None();
- Representation representation_from_non_phi_uses_ = Representation::None();
- bool has_type_feedback_from_uses_ = false;
-
- // TODO(titzer): we can't eliminate the receiver for generating backtraces
- bool IsDeletable() const override { return !IsReceiver(); }
-};
-
-
-// Common base class for HArgumentsObject and HCapturedObject.
-class HDematerializedObject : public HInstruction {
- public:
- HDematerializedObject(int count, Zone* zone) : values_(count, zone) {}
-
- int OperandCount() const final { return values_.length(); }
- HValue* OperandAt(int index) const final { return values_[index]; }
-
- bool HasEscapingOperandAt(int index) final { return false; }
- Representation RequiredInputRepresentation(int index) final {
- return Representation::None();
- }
-
- protected:
- void InternalSetOperandAt(int index, HValue* value) final {
- values_[index] = value;
- }
-
- // List of values tracked by this marker.
- ZoneList<HValue*> values_;
-};
-
-
-class HArgumentsObject final : public HDematerializedObject {
- public:
- static HArgumentsObject* New(Isolate* isolate, Zone* zone, HValue* context,
- int count) {
- return new(zone) HArgumentsObject(count, zone);
- }
-
- // The values contain a list of all elements in the arguments object
- // including the receiver object, which is skipped when materializing.
- const ZoneList<HValue*>* arguments_values() const { return &values_; }
- int arguments_count() const { return values_.length(); }
-
- void AddArgument(HValue* argument, Zone* zone) {
- values_.Add(NULL, zone); // Resize list.
- SetOperandAt(values_.length() - 1, argument);
- }
-
- DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
-
- private:
- HArgumentsObject(int count, Zone* zone)
- : HDematerializedObject(count, zone) {
- set_representation(Representation::Tagged());
- SetFlag(kIsArguments);
- }
-};
-
-
-class HCapturedObject final : public HDematerializedObject {
- public:
- HCapturedObject(int length, int id, Zone* zone)
- : HDematerializedObject(length, zone), capture_id_(id) {
- set_representation(Representation::Tagged());
- values_.AddBlock(NULL, length, zone); // Resize list.
- }
-
- // The values contain a list of all in-object properties inside the
- // captured object and is index by field index. Properties in the
- // properties or elements backing store are not tracked here.
- const ZoneList<HValue*>* values() const { return &values_; }
- int length() const { return values_.length(); }
- int capture_id() const { return capture_id_; }
-
- // Shortcut for the map value of this captured object.
- HValue* map_value() const { return values()->first(); }
-
- void ReuseSideEffectsFromStore(HInstruction* store) {
- DCHECK(store->HasObservableSideEffects());
- DCHECK(store->IsStoreNamedField());
- changes_flags_.Add(store->ChangesFlags());
- }
-
- // Replay effects of this instruction on the given environment.
- void ReplayEnvironment(HEnvironment* env);
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- DECLARE_CONCRETE_INSTRUCTION(CapturedObject)
-
- private:
- int capture_id_;
-
- // Note that we cannot DCE captured objects as they are used to replay
- // the environment. This method is here as an explicit reminder.
- // TODO(mstarzinger): Turn HSimulates into full snapshots maybe?
- bool IsDeletable() const final { return false; }
-};
-
-
-class HConstant final : public HTemplateInstruction<0> {
- public:
- enum Special { kHoleNaN };
-
- DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Special);
- DECLARE_INSTRUCTION_FACTORY_P1(HConstant, int32_t);
- DECLARE_INSTRUCTION_FACTORY_P2(HConstant, int32_t, Representation);
- DECLARE_INSTRUCTION_FACTORY_P1(HConstant, double);
- DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Handle<Object>);
- DECLARE_INSTRUCTION_FACTORY_P1(HConstant, ExternalReference);
-
- static HConstant* CreateAndInsertAfter(Isolate* isolate, Zone* zone,
- HValue* context, int32_t value,
- Representation representation,
- HInstruction* instruction) {
- return instruction->Append(
- HConstant::New(isolate, zone, context, value, representation));
- }
-
- Handle<Map> GetMonomorphicJSObjectMap() override {
- Handle<Object> object = object_.handle();
- if (!object.is_null() && object->IsHeapObject()) {
- return v8::internal::handle(HeapObject::cast(*object)->map());
- }
- return Handle<Map>();
- }
-
- static HConstant* CreateAndInsertBefore(Isolate* isolate, Zone* zone,
- HValue* context, int32_t value,
- Representation representation,
- HInstruction* instruction) {
- return instruction->Prepend(
- HConstant::New(isolate, zone, context, value, representation));
- }
-
- static HConstant* CreateAndInsertBefore(Zone* zone,
- Unique<Map> map,
- bool map_is_stable,
- HInstruction* instruction) {
- return instruction->Prepend(new(zone) HConstant(
- map, Unique<Map>(Handle<Map>::null()), map_is_stable,
- Representation::Tagged(), HType::HeapObject(), true,
- false, false, MAP_TYPE));
- }
-
- static HConstant* CreateAndInsertAfter(Zone* zone,
- Unique<Map> map,
- bool map_is_stable,
- HInstruction* instruction) {
- return instruction->Append(new(zone) HConstant(
- map, Unique<Map>(Handle<Map>::null()), map_is_stable,
- Representation::Tagged(), HType::HeapObject(), true,
- false, false, MAP_TYPE));
- }
-
- Handle<Object> handle(Isolate* isolate) {
- if (object_.handle().is_null()) {
- // Default arguments to is_not_in_new_space depend on this heap number
- // to be tenured so that it's guaranteed not to be located in new space.
- object_ = Unique<Object>::CreateUninitialized(
- isolate->factory()->NewNumber(double_value_, TENURED));
- }
- AllowDeferredHandleDereference smi_check;
- DCHECK(HasInteger32Value() || !object_.handle()->IsSmi());
- return object_.handle();
- }
-
- bool IsSpecialDouble() const {
- return HasDoubleValue() &&
- (bit_cast<int64_t>(double_value_) == bit_cast<int64_t>(-0.0) ||
- std::isnan(double_value_));
- }
-
- bool NotInNewSpace() const {
- return IsNotInNewSpaceField::decode(bit_field_);
- }
-
- bool ImmortalImmovable() const;
-
- bool IsCell() const {
- InstanceType instance_type = GetInstanceType();
- return instance_type == CELL_TYPE;
- }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
-
- Representation KnownOptimalRepresentation() override {
- if (HasSmiValue() && SmiValuesAre31Bits()) return Representation::Smi();
- if (HasInteger32Value()) return Representation::Integer32();
- if (HasNumberValue()) return Representation::Double();
- if (HasExternalReferenceValue()) return Representation::External();
- return Representation::Tagged();
- }
-
- bool EmitAtUses() override;
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
- HConstant* CopyToRepresentation(Representation r, Zone* zone) const;
- Maybe<HConstant*> CopyToTruncatedInt32(Zone* zone);
- Maybe<HConstant*> CopyToTruncatedNumber(Isolate* isolate, Zone* zone);
- bool HasInteger32Value() const {
- return HasInt32ValueField::decode(bit_field_);
- }
- int32_t Integer32Value() const {
- DCHECK(HasInteger32Value());
- return int32_value_;
- }
- bool HasSmiValue() const { return HasSmiValueField::decode(bit_field_); }
- bool HasDoubleValue() const {
- return HasDoubleValueField::decode(bit_field_);
- }
- double DoubleValue() const {
- DCHECK(HasDoubleValue());
- return double_value_;
- }
- uint64_t DoubleValueAsBits() const {
- uint64_t bits;
- DCHECK(HasDoubleValue());
- STATIC_ASSERT(sizeof(bits) == sizeof(double_value_));
- std::memcpy(&bits, &double_value_, sizeof(bits));
- return bits;
- }
- bool IsTheHole() const {
- if (HasDoubleValue() && DoubleValueAsBits() == kHoleNanInt64) {
- return true;
- }
- return object_.IsInitialized() &&
- object_.IsKnownGlobal(isolate()->heap()->the_hole_value());
- }
- bool HasNumberValue() const { return HasDoubleValue(); }
- int32_t NumberValueAsInteger32() const {
- DCHECK(HasNumberValue());
- // Irrespective of whether a numeric HConstant can be safely
- // represented as an int32, we store the (in some cases lossy)
- // representation of the number in int32_value_.
- return int32_value_;
- }
- bool HasStringValue() const {
- if (HasNumberValue()) return false;
- DCHECK(!object_.handle().is_null());
- return GetInstanceType() < FIRST_NONSTRING_TYPE;
- }
- Handle<String> StringValue() const {
- DCHECK(HasStringValue());
- return Handle<String>::cast(object_.handle());
- }
- bool HasInternalizedStringValue() const {
- return HasStringValue() && StringShape(GetInstanceType()).IsInternalized();
- }
-
- bool HasExternalReferenceValue() const {
- return HasExternalReferenceValueField::decode(bit_field_);
- }
- ExternalReference ExternalReferenceValue() const {
- return external_reference_value_;
- }
-
- bool HasBooleanValue() const { return type_.IsBoolean(); }
- bool BooleanValue() const { return BooleanValueField::decode(bit_field_); }
- bool IsCallable() const { return IsCallableField::decode(bit_field_); }
- bool IsUndetectable() const {
- return IsUndetectableField::decode(bit_field_);
- }
- InstanceType GetInstanceType() const {
- return InstanceTypeField::decode(bit_field_);
- }
-
- bool HasMapValue() const { return GetInstanceType() == MAP_TYPE; }
- Unique<Map> MapValue() const {
- DCHECK(HasMapValue());
- return Unique<Map>::cast(GetUnique());
- }
- bool HasStableMapValue() const {
- DCHECK(HasMapValue() || !HasStableMapValueField::decode(bit_field_));
- return HasStableMapValueField::decode(bit_field_);
- }
-
- bool HasObjectMap() const { return !object_map_.IsNull(); }
- Unique<Map> ObjectMap() const {
- DCHECK(HasObjectMap());
- return object_map_;
- }
-
- intptr_t Hashcode() override {
- if (HasInteger32Value()) {
- return static_cast<intptr_t>(int32_value_);
- } else if (HasDoubleValue()) {
- uint64_t bits = DoubleValueAsBits();
- if (sizeof(bits) > sizeof(intptr_t)) {
- bits ^= (bits >> 32);
- }
- return static_cast<intptr_t>(bits);
- } else if (HasExternalReferenceValue()) {
- return reinterpret_cast<intptr_t>(external_reference_value_.address());
- } else {
- DCHECK(!object_.handle().is_null());
- return object_.Hashcode();
- }
- }
-
- void FinalizeUniqueness() override {
- if (!HasDoubleValue() && !HasExternalReferenceValue()) {
- DCHECK(!object_.handle().is_null());
- object_ = Unique<Object>(object_.handle());
- }
- }
-
- Unique<Object> GetUnique() const {
- return object_;
- }
-
- bool EqualsUnique(Unique<Object> other) const {
- return object_.IsInitialized() && object_ == other;
- }
-
- bool DataEquals(HValue* other) override {
- HConstant* other_constant = HConstant::cast(other);
- if (HasInteger32Value()) {
- return other_constant->HasInteger32Value() &&
- int32_value_ == other_constant->int32_value_;
- } else if (HasDoubleValue()) {
- return other_constant->HasDoubleValue() &&
- std::memcmp(&double_value_, &other_constant->double_value_,
- sizeof(double_value_)) == 0;
- } else if (HasExternalReferenceValue()) {
- return other_constant->HasExternalReferenceValue() &&
- external_reference_value_ ==
- other_constant->external_reference_value_;
- } else {
- if (other_constant->HasInteger32Value() ||
- other_constant->HasDoubleValue() ||
- other_constant->HasExternalReferenceValue()) {
- return false;
- }
- DCHECK(!object_.handle().is_null());
- return other_constant->object_ == object_;
- }
- }
-
-#ifdef DEBUG
- void Verify() override {}
-#endif
-
- DECLARE_CONCRETE_INSTRUCTION(Constant)
-
- protected:
- Range* InferRange(Zone* zone) override;
-
- private:
- friend class HGraph;
- explicit HConstant(Special special);
- explicit HConstant(Handle<Object> handle,
- Representation r = Representation::None());
- HConstant(int32_t value,
- Representation r = Representation::None(),
- bool is_not_in_new_space = true,
- Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
- HConstant(double value,
- Representation r = Representation::None(),
- bool is_not_in_new_space = true,
- Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
- HConstant(Unique<Object> object,
- Unique<Map> object_map,
- bool has_stable_map_value,
- Representation r,
- HType type,
- bool is_not_in_new_space,
- bool boolean_value,
- bool is_undetectable,
- InstanceType instance_type);
-
- explicit HConstant(ExternalReference reference);
-
- void Initialize(Representation r);
-
- bool IsDeletable() const override { return true; }
-
- // If object_ is a map, this indicates whether the map is stable.
- class HasStableMapValueField : public BitField<bool, 0, 1> {};
-
- // We store the HConstant in the most specific form safely possible.
- // These flags tell us if the respective member fields hold valid, safe
- // representations of the constant. More specific flags imply more general
- // flags, but not the converse (i.e. smi => int32 => double).
- class HasSmiValueField : public BitField<bool, 1, 1> {};
- class HasInt32ValueField : public BitField<bool, 2, 1> {};
- class HasDoubleValueField : public BitField<bool, 3, 1> {};
-
- class HasExternalReferenceValueField : public BitField<bool, 4, 1> {};
- class IsNotInNewSpaceField : public BitField<bool, 5, 1> {};
- class BooleanValueField : public BitField<bool, 6, 1> {};
- class IsUndetectableField : public BitField<bool, 7, 1> {};
- class IsCallableField : public BitField<bool, 8, 1> {};
-
- static const InstanceType kUnknownInstanceType = FILLER_TYPE;
- class InstanceTypeField : public BitField<InstanceType, 16, 8> {};
-
- // If this is a numerical constant, object_ either points to the
- // HeapObject the constant originated from or is null. If the
- // constant is non-numeric, object_ always points to a valid
- // constant HeapObject.
- Unique<Object> object_;
-
- // If object_ is a heap object, this points to the stable map of the object.
- Unique<Map> object_map_;
-
- uint32_t bit_field_;
-
- int32_t int32_value_;
- double double_value_;
- ExternalReference external_reference_value_;
-};
-
-
-class HBinaryOperation : public HTemplateInstruction<3> {
- public:
- HBinaryOperation(HValue* context, HValue* left, HValue* right,
- Strength strength, HType type = HType::Tagged())
- : HTemplateInstruction<3>(type),
- strength_(strength),
- observed_output_representation_(Representation::None()) {
- DCHECK(left != NULL && right != NULL);
- SetOperandAt(0, context);
- SetOperandAt(1, left);
- SetOperandAt(2, right);
- observed_input_representation_[0] = Representation::None();
- observed_input_representation_[1] = Representation::None();
- }
-
- HValue* context() const { return OperandAt(0); }
- HValue* left() const { return OperandAt(1); }
- HValue* right() const { return OperandAt(2); }
- Strength strength() const { return strength_; }
-
- // True if switching left and right operands likely generates better code.
- bool AreOperandsBetterSwitched() {
- if (!IsCommutative()) return false;
-
- // Constant operands are better off on the right, they can be inlined in
- // many situations on most platforms.
- if (left()->IsConstant()) return true;
- if (right()->IsConstant()) return false;
-
- // Otherwise, if there is only one use of the right operand, it would be
- // better off on the left for platforms that only have 2-arg arithmetic
- // ops (e.g ia32, x64) that clobber the left operand.
- return right()->HasOneUse();
- }
-
- HValue* BetterLeftOperand() {
- return AreOperandsBetterSwitched() ? right() : left();
- }
-
- HValue* BetterRightOperand() {
- return AreOperandsBetterSwitched() ? left() : right();
- }
-
- void set_observed_input_representation(int index, Representation rep) {
- DCHECK(index >= 1 && index <= 2);
- observed_input_representation_[index - 1] = rep;
- }
-
- virtual void initialize_output_representation(Representation observed) {
- observed_output_representation_ = observed;
- }
-
- Representation observed_input_representation(int index) override {
- if (index == 0) return Representation::Tagged();
- return observed_input_representation_[index - 1];
- }
-
- virtual void UpdateRepresentation(Representation new_rep,
- HInferRepresentationPhase* h_infer,
- const char* reason) override {
- Representation rep = !FLAG_smi_binop && new_rep.IsSmi()
- ? Representation::Integer32() : new_rep;
- HValue::UpdateRepresentation(rep, h_infer, reason);
- }
-
- virtual void InferRepresentation(HInferRepresentationPhase* h_infer) override;
- Representation RepresentationFromInputs() override;
- Representation RepresentationFromOutput();
- void AssumeRepresentation(Representation r) override;
-
- virtual bool IsCommutative() const { return false; }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- Representation RequiredInputRepresentation(int index) override {
- if (index == 0) return Representation::Tagged();
- return representation();
- }
-
- void SetOperandPositions(Zone* zone, SourcePosition left_pos,
- SourcePosition right_pos) {
- set_operand_position(zone, 1, left_pos);
- set_operand_position(zone, 2, right_pos);
- }
-
- bool RightIsPowerOf2() {
- if (!right()->IsInteger32Constant()) return false;
- int32_t value = right()->GetInteger32Constant();
- if (value < 0) {
- return base::bits::IsPowerOfTwo32(static_cast<uint32_t>(-value));
- }
- return base::bits::IsPowerOfTwo32(static_cast<uint32_t>(value));
- }
-
- Strength strength() { return strength_; }
-
- DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation)
-
- private:
- bool IgnoreObservedOutputRepresentation(Representation current_rep);
- Strength strength_;
-
- Representation observed_input_representation_[2];
- Representation observed_output_representation_;
-};
-
-
-class HWrapReceiver final : public HTemplateInstruction<2> {
- public:
- DECLARE_INSTRUCTION_FACTORY_P2(HWrapReceiver, HValue*, HValue*);
-
- bool DataEquals(HValue* other) override { return true; }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- HValue* receiver() const { return OperandAt(0); }
- HValue* function() const { return OperandAt(1); }
-
- HValue* Canonicalize() override;
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
- bool known_function() const { return known_function_; }
-
- DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
-
- private:
- HWrapReceiver(HValue* receiver, HValue* function) {
- known_function_ = function->IsConstant() &&
- HConstant::cast(function)->handle(function->isolate())->IsJSFunction();
- set_representation(Representation::Tagged());
- SetOperandAt(0, receiver);
- SetOperandAt(1, function);
- SetFlag(kUseGVN);
- }
-
- bool known_function_;
-};
-
-
-class HApplyArguments final : public HTemplateInstruction<4> {
- public:
- DECLARE_INSTRUCTION_FACTORY_P4(HApplyArguments, HValue*, HValue*, HValue*,
- HValue*);
-
- Representation RequiredInputRepresentation(int index) override {
- // The length is untagged, all other inputs are tagged.
- return (index == 2)
- ? Representation::Integer32()
- : Representation::Tagged();
- }
-
- HValue* function() { return OperandAt(0); }
- HValue* receiver() { return OperandAt(1); }
- HValue* length() { return OperandAt(2); }
- HValue* elements() { return OperandAt(3); }
-
- DECLARE_CONCRETE_INSTRUCTION(ApplyArguments)
-
- private:
- HApplyArguments(HValue* function,
- HValue* receiver,
- HValue* length,
- HValue* elements) {
- set_representation(Representation::Tagged());
- SetOperandAt(0, function);
- SetOperandAt(1, receiver);
- SetOperandAt(2, length);
- SetOperandAt(3, elements);
- SetAllSideEffects();
- }
-};
-
-
-class HArgumentsElements final : public HTemplateInstruction<0> {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsElements, bool);
-
- DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
-
- bool from_inlined() const { return from_inlined_; }
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- private:
- explicit HArgumentsElements(bool from_inlined) : from_inlined_(from_inlined) {
- // The value produced by this instruction is a pointer into the stack
- // that looks as if it was a smi because of alignment.
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- }
-
- bool IsDeletable() const override { return true; }
-
- bool from_inlined_;
-};
-
-
-class HArgumentsLength final : public HUnaryOperation {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsLength, HValue*);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- private:
- explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
- set_representation(Representation::Integer32());
- SetFlag(kUseGVN);
- }
-
- bool IsDeletable() const override { return true; }
-};
-
-
-class HAccessArgumentsAt final : public HTemplateInstruction<3> {
- public:
- DECLARE_INSTRUCTION_FACTORY_P3(HAccessArgumentsAt, HValue*, HValue*, HValue*);
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- Representation RequiredInputRepresentation(int index) override {
- // The arguments elements is considered tagged.
- return index == 0
- ? Representation::Tagged()
- : Representation::Integer32();
- }
-
- HValue* arguments() const { return OperandAt(0); }
- HValue* length() const { return OperandAt(1); }
- HValue* index() const { return OperandAt(2); }
-
- DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)
-
- private:
- HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetOperandAt(0, arguments);
- SetOperandAt(1, length);
- SetOperandAt(2, index);
- }
-
- bool DataEquals(HValue* other) override { return true; }
-};
-
-
-class HBoundsCheckBaseIndexInformation;
-
-
-class HBoundsCheck final : public HTemplateInstruction<2> {
- public:
- DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*);
-
- bool skip_check() const { return skip_check_; }
- void set_skip_check() { skip_check_ = true; }
-
- HValue* base() const { return base_; }
- int offset() const { return offset_; }
- int scale() const { return scale_; }
-
- void ApplyIndexChange();
- bool DetectCompoundIndex() {
- DCHECK(base() == NULL);
-
- DecompositionResult decomposition;
- if (index()->TryDecompose(&decomposition)) {
- base_ = decomposition.base();
- offset_ = decomposition.offset();
- scale_ = decomposition.scale();
- return true;
- } else {
- base_ = index();
- offset_ = 0;
- scale_ = 0;
- return false;
- }
- }
-
- Representation RequiredInputRepresentation(int index) override {
- return representation();
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
- virtual void InferRepresentation(HInferRepresentationPhase* h_infer) override;
-
- HValue* index() const { return OperandAt(0); }
- HValue* length() const { return OperandAt(1); }
- bool allow_equality() const { return allow_equality_; }
- void set_allow_equality(bool v) { allow_equality_ = v; }
-
- int RedefinedOperandIndex() override { return 0; }
- bool IsPurelyInformativeDefinition() override { return skip_check(); }
-
- DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
-
- protected:
- friend class HBoundsCheckBaseIndexInformation;
-
- Range* InferRange(Zone* zone) override;
-
- bool DataEquals(HValue* other) override { return true; }
- bool skip_check_;
- HValue* base_;
- int offset_;
- int scale_;
- bool allow_equality_;
-
- private:
- // Normally HBoundsCheck should be created using the
- // HGraphBuilder::AddBoundsCheck() helper.
- // However when building stubs, where we know that the arguments are Int32,
- // it makes sense to invoke this constructor directly.
- HBoundsCheck(HValue* index, HValue* length)
- : skip_check_(false),
- base_(NULL), offset_(0), scale_(0),
- allow_equality_(false) {
- SetOperandAt(0, index);
- SetOperandAt(1, length);
- SetFlag(kFlexibleRepresentation);
- SetFlag(kUseGVN);
- }
-
- bool IsDeletable() const override { return skip_check() && !FLAG_debug_code; }
-};
-
-
-class HBoundsCheckBaseIndexInformation final : public HTemplateInstruction<2> {
- public:
- explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) {
- DecompositionResult decomposition;
- if (check->index()->TryDecompose(&decomposition)) {
- SetOperandAt(0, decomposition.base());
- SetOperandAt(1, check);
- } else {
- UNREACHABLE();
- }
- }
-
- HValue* base_index() const { return OperandAt(0); }
- HBoundsCheck* bounds_check() { return HBoundsCheck::cast(OperandAt(1)); }
-
- DECLARE_CONCRETE_INSTRUCTION(BoundsCheckBaseIndexInformation)
-
- Representation RequiredInputRepresentation(int index) override {
- return representation();
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- int RedefinedOperandIndex() override { return 0; }
- bool IsPurelyInformativeDefinition() override { return true; }
-};
-
-
-class HBitwiseBinaryOperation : public HBinaryOperation {
- public:
- HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right,
- Strength strength, HType type = HType::TaggedNumber())
- : HBinaryOperation(context, left, right, strength, type) {
- SetFlag(kFlexibleRepresentation);
- SetFlag(kTruncatingToInt32);
- if (!is_strong(strength)) SetFlag(kAllowUndefinedAsNaN);
- SetAllSideEffects();
- }
-
- void RepresentationChanged(Representation to) override {
- if (to.IsTagged() &&
- (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
- SetAllSideEffects();
- ClearFlag(kUseGVN);
- } else {
- ClearAllSideEffects();
- SetFlag(kUseGVN);
- }
- if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
- }
-
- virtual void UpdateRepresentation(Representation new_rep,
- HInferRepresentationPhase* h_infer,
- const char* reason) override {
- // We only generate either int32 or generic tagged bitwise operations.
- if (new_rep.IsDouble()) new_rep = Representation::Integer32();
- HBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
- }
-
- Representation observed_input_representation(int index) override {
- Representation r = HBinaryOperation::observed_input_representation(index);
- if (r.IsDouble()) return Representation::Integer32();
- return r;
- }
-
- virtual void initialize_output_representation(
- Representation observed) override {
- if (observed.IsDouble()) observed = Representation::Integer32();
- HBinaryOperation::initialize_output_representation(observed);
- }
-
- DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
-
- private:
- bool IsDeletable() const override { return true; }
-};
-
-
-class HMathFloorOfDiv final : public HBinaryOperation {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HMathFloorOfDiv,
- HValue*,
- HValue*);
-
- DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- private:
- HMathFloorOfDiv(HValue* context, HValue* left, HValue* right)
- : HBinaryOperation(context, left, right, Strength::WEAK) {
- set_representation(Representation::Integer32());
- SetFlag(kUseGVN);
- SetFlag(kCanOverflow);
- SetFlag(kCanBeDivByZero);
- SetFlag(kLeftCanBeMinInt);
- SetFlag(kLeftCanBeNegative);
- SetFlag(kLeftCanBePositive);
- SetFlag(kAllowUndefinedAsNaN);
- }
-
- Range* InferRange(Zone* zone) override;
-
- bool IsDeletable() const override { return true; }
-};
-
-
-class HArithmeticBinaryOperation : public HBinaryOperation {
- public:
- HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right,
- Strength strength)
- : HBinaryOperation(context, left, right, strength,
- HType::TaggedNumber()) {
- SetAllSideEffects();
- SetFlag(kFlexibleRepresentation);
- if (!is_strong(strength)) SetFlag(kAllowUndefinedAsNaN);
- }
-
- void RepresentationChanged(Representation to) override {
- if (to.IsTagged() &&
- (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
- SetAllSideEffects();
- ClearFlag(kUseGVN);
- } else {
- ClearAllSideEffects();
- SetFlag(kUseGVN);
- }
- if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
- }
-
- DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)
-
- private:
- bool IsDeletable() const override { return true; }
-};
-
-
-class HCompareGeneric final : public HBinaryOperation {
- public:
- static HCompareGeneric* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* left, HValue* right, Token::Value token,
- Strength strength = Strength::WEAK) {
- return new (zone) HCompareGeneric(context, left, right, token, strength);
- }
-
- Representation RequiredInputRepresentation(int index) override {
- return index == 0
- ? Representation::Tagged()
- : representation();
- }
-
- Token::Value token() const { return token_; }
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
-
- private:
- HCompareGeneric(HValue* context, HValue* left, HValue* right,
- Token::Value token, Strength strength)
- : HBinaryOperation(context, left, right, strength, HType::Boolean()),
- token_(token) {
- DCHECK(Token::IsCompareOp(token));
- set_representation(Representation::Tagged());
- SetAllSideEffects();
- }
-
- Token::Value token_;
-};
-
-
-class HCompareNumericAndBranch : public HTemplateControlInstruction<2, 2> {
- public:
- static HCompareNumericAndBranch* New(Isolate* isolate, Zone* zone,
- HValue* context, HValue* left,
- HValue* right, Token::Value token,
- HBasicBlock* true_target = NULL,
- HBasicBlock* false_target = NULL,
- Strength strength = Strength::WEAK) {
- return new (zone) HCompareNumericAndBranch(left, right, token, true_target,
- false_target, strength);
- }
- static HCompareNumericAndBranch* New(Isolate* isolate, Zone* zone,
- HValue* context, HValue* left,
- HValue* right, Token::Value token,
- Strength strength) {
- return new (zone)
- HCompareNumericAndBranch(left, right, token, NULL, NULL, strength);
- }
-
- HValue* left() const { return OperandAt(0); }
- HValue* right() const { return OperandAt(1); }
- Token::Value token() const { return token_; }
-
- void set_observed_input_representation(Representation left,
- Representation right) {
- observed_input_representation_[0] = left;
- observed_input_representation_[1] = right;
- }
-
- virtual void InferRepresentation(HInferRepresentationPhase* h_infer) override;
-
- Representation RequiredInputRepresentation(int index) override {
- return representation();
- }
- Representation observed_input_representation(int index) override {
- return observed_input_representation_[index];
- }
-
- bool KnownSuccessorBlock(HBasicBlock** block) override;
-
- Strength strength() const { return strength_; }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- void SetOperandPositions(Zone* zone, SourcePosition left_pos,
- SourcePosition right_pos) {
- set_operand_position(zone, 0, left_pos);
- set_operand_position(zone, 1, right_pos);
- }
-
- DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)
-
- private:
- HCompareNumericAndBranch(HValue* left, HValue* right, Token::Value token,
- HBasicBlock* true_target, HBasicBlock* false_target,
- Strength strength)
- : token_(token), strength_(strength) {
- SetFlag(kFlexibleRepresentation);
- DCHECK(Token::IsCompareOp(token));
- SetOperandAt(0, left);
- SetOperandAt(1, right);
- SetSuccessorAt(0, true_target);
- SetSuccessorAt(1, false_target);
- }
-
- Representation observed_input_representation_[2];
- Token::Value token_;
- Strength strength_;
-};
-
-
-class HCompareHoleAndBranch final : public HUnaryControlInstruction {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HCompareHoleAndBranch, HValue*);
- DECLARE_INSTRUCTION_FACTORY_P3(HCompareHoleAndBranch, HValue*,
- HBasicBlock*, HBasicBlock*);
-
- virtual void InferRepresentation(HInferRepresentationPhase* h_infer) override;
-
- Representation RequiredInputRepresentation(int index) override {
- return representation();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(CompareHoleAndBranch)
-
- private:
- HCompareHoleAndBranch(HValue* value,
- HBasicBlock* true_target = NULL,
- HBasicBlock* false_target = NULL)
- : HUnaryControlInstruction(value, true_target, false_target) {
- SetFlag(kFlexibleRepresentation);
- SetFlag(kAllowUndefinedAsNaN);
- }
-};
-
-
-class HCompareMinusZeroAndBranch final : public HUnaryControlInstruction {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HCompareMinusZeroAndBranch, HValue*);
-
- virtual void InferRepresentation(HInferRepresentationPhase* h_infer) override;
-
- Representation RequiredInputRepresentation(int index) override {
- return representation();
- }
-
- bool KnownSuccessorBlock(HBasicBlock** block) override;
-
- DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch)
-
- private:
- explicit HCompareMinusZeroAndBranch(HValue* value)
- : HUnaryControlInstruction(value, NULL, NULL) {
- }
-};
-
-
-class HCompareObjectEqAndBranch : public HTemplateControlInstruction<2, 2> {
- public:
- DECLARE_INSTRUCTION_FACTORY_P2(HCompareObjectEqAndBranch, HValue*, HValue*);
- DECLARE_INSTRUCTION_FACTORY_P4(HCompareObjectEqAndBranch, HValue*, HValue*,
- HBasicBlock*, HBasicBlock*);
-
- bool KnownSuccessorBlock(HBasicBlock** block) override;
-
- static const int kNoKnownSuccessorIndex = -1;
- int known_successor_index() const { return known_successor_index_; }
- void set_known_successor_index(int known_successor_index) {
- known_successor_index_ = known_successor_index;
- }
-
- HValue* left() const { return OperandAt(0); }
- HValue* right() const { return OperandAt(1); }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- Representation observed_input_representation(int index) override {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)
-
- private:
- HCompareObjectEqAndBranch(HValue* left,
- HValue* right,
- HBasicBlock* true_target = NULL,
- HBasicBlock* false_target = NULL)
- : known_successor_index_(kNoKnownSuccessorIndex) {
- SetOperandAt(0, left);
- SetOperandAt(1, right);
- SetSuccessorAt(0, true_target);
- SetSuccessorAt(1, false_target);
- }
-
- int known_successor_index_;
-};
-
-
-class HIsStringAndBranch final : public HUnaryControlInstruction {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HIsStringAndBranch, HValue*);
- DECLARE_INSTRUCTION_FACTORY_P3(HIsStringAndBranch, HValue*,
- HBasicBlock*, HBasicBlock*);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- bool KnownSuccessorBlock(HBasicBlock** block) override;
-
- static const int kNoKnownSuccessorIndex = -1;
- int known_successor_index() const { return known_successor_index_; }
- void set_known_successor_index(int known_successor_index) {
- known_successor_index_ = known_successor_index;
- }
-
- DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
-
- protected:
- int RedefinedOperandIndex() override { return 0; }
-
- private:
- HIsStringAndBranch(HValue* value, HBasicBlock* true_target = NULL,
- HBasicBlock* false_target = NULL)
- : HUnaryControlInstruction(value, true_target, false_target),
- known_successor_index_(kNoKnownSuccessorIndex) {
- set_representation(Representation::Tagged());
- }
-
- int known_successor_index_;
-};
-
-
-class HIsSmiAndBranch final : public HUnaryControlInstruction {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HIsSmiAndBranch, HValue*);
- DECLARE_INSTRUCTION_FACTORY_P3(HIsSmiAndBranch, HValue*,
- HBasicBlock*, HBasicBlock*);
-
- DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
- int RedefinedOperandIndex() override { return 0; }
-
- private:
- HIsSmiAndBranch(HValue* value,
- HBasicBlock* true_target = NULL,
- HBasicBlock* false_target = NULL)
- : HUnaryControlInstruction(value, true_target, false_target) {
- set_representation(Representation::Tagged());
- }
-};
-
-
-class HIsUndetectableAndBranch final : public HUnaryControlInstruction {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HIsUndetectableAndBranch, HValue*);
- DECLARE_INSTRUCTION_FACTORY_P3(HIsUndetectableAndBranch, HValue*,
- HBasicBlock*, HBasicBlock*);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- bool KnownSuccessorBlock(HBasicBlock** block) override;
-
- DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)
-
- private:
- HIsUndetectableAndBranch(HValue* value,
- HBasicBlock* true_target = NULL,
- HBasicBlock* false_target = NULL)
- : HUnaryControlInstruction(value, true_target, false_target) {}
-};
-
-
-class HStringCompareAndBranch final : public HTemplateControlInstruction<2, 3> {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HStringCompareAndBranch,
- HValue*,
- HValue*,
- Token::Value);
-
- HValue* context() const { return OperandAt(0); }
- HValue* left() const { return OperandAt(1); }
- HValue* right() const { return OperandAt(2); }
- Token::Value token() const { return token_; }
-
- std::ostream& PrintDataTo(std::ostream& os) const final; // NOLINT
-
- Representation RequiredInputRepresentation(int index) final {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)
-
- private:
- HStringCompareAndBranch(HValue* context, HValue* left, HValue* right,
- Token::Value token)
- : token_(token) {
- DCHECK(Token::IsCompareOp(token));
- SetOperandAt(0, context);
- SetOperandAt(1, left);
- SetOperandAt(2, right);
- set_representation(Representation::Tagged());
- SetChangesFlag(kNewSpacePromotion);
- SetDependsOnFlag(kStringChars);
- SetDependsOnFlag(kStringLengths);
- }
-
- Token::Value const token_;
-};
-
-
-class HIsConstructCallAndBranch : public HTemplateControlInstruction<2, 0> {
- public:
- DECLARE_INSTRUCTION_FACTORY_P0(HIsConstructCallAndBranch);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch)
- private:
- HIsConstructCallAndBranch() {}
-};
-
-
-class HHasInstanceTypeAndBranch final : public HUnaryControlInstruction {
- public:
- DECLARE_INSTRUCTION_FACTORY_P2(
- HHasInstanceTypeAndBranch, HValue*, InstanceType);
- DECLARE_INSTRUCTION_FACTORY_P3(
- HHasInstanceTypeAndBranch, HValue*, InstanceType, InstanceType);
-
- InstanceType from() { return from_; }
- InstanceType to() { return to_; }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- bool KnownSuccessorBlock(HBasicBlock** block) override;
-
- DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
-
- private:
- HHasInstanceTypeAndBranch(HValue* value, InstanceType type)
- : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { }
- HHasInstanceTypeAndBranch(HValue* value, InstanceType from, InstanceType to)
- : HUnaryControlInstruction(value, NULL, NULL), from_(from), to_(to) {
- DCHECK(to == LAST_TYPE); // Others not implemented yet in backend.
- }
-
- InstanceType from_;
- InstanceType to_; // Inclusive range, not all combinations work.
-};
-
-
-class HHasCachedArrayIndexAndBranch final : public HUnaryControlInstruction {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HHasCachedArrayIndexAndBranch, HValue*);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch)
- private:
- explicit HHasCachedArrayIndexAndBranch(HValue* value)
- : HUnaryControlInstruction(value, NULL, NULL) { }
-};
-
-
-class HGetCachedArrayIndex final : public HUnaryOperation {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HGetCachedArrayIndex, HValue*);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- private:
- explicit HGetCachedArrayIndex(HValue* value) : HUnaryOperation(value) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- }
-
- bool IsDeletable() const override { return true; }
-};
-
-
-class HClassOfTestAndBranch final : public HUnaryControlInstruction {
- public:
- DECLARE_INSTRUCTION_FACTORY_P2(HClassOfTestAndBranch, HValue*,
- Handle<String>);
-
- DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- Handle<String> class_name() const { return class_name_; }
-
- private:
- HClassOfTestAndBranch(HValue* value, Handle<String> class_name)
- : HUnaryControlInstruction(value, NULL, NULL),
- class_name_(class_name) { }
-
- Handle<String> class_name_;
-};
-
-
-class HTypeofIsAndBranch final : public HUnaryControlInstruction {
- public:
- DECLARE_INSTRUCTION_FACTORY_P2(HTypeofIsAndBranch, HValue*, Handle<String>);
-
- Handle<String> type_literal() const { return type_literal_.handle(); }
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
-
- bool KnownSuccessorBlock(HBasicBlock** block) override;
-
- void FinalizeUniqueness() override {
- type_literal_ = Unique<String>(type_literal_.handle());
- }
-
- private:
- HTypeofIsAndBranch(HValue* value, Handle<String> type_literal)
- : HUnaryControlInstruction(value, NULL, NULL),
- type_literal_(Unique<String>::CreateUninitialized(type_literal)) { }
-
- Unique<String> type_literal_;
-};
-
-
-class HInstanceOf final : public HBinaryOperation {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInstanceOf, HValue*, HValue*);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- DECLARE_CONCRETE_INSTRUCTION(InstanceOf)
-
- private:
- HInstanceOf(HValue* context, HValue* left, HValue* right)
- : HBinaryOperation(context, left, right, Strength::WEAK,
- HType::Boolean()) {
- set_representation(Representation::Tagged());
- SetAllSideEffects();
- }
-};
-
-
-class HHasInPrototypeChainAndBranch final
- : public HTemplateControlInstruction<2, 2> {
- public:
- DECLARE_INSTRUCTION_FACTORY_P2(HHasInPrototypeChainAndBranch, HValue*,
- HValue*);
-
- HValue* object() const { return OperandAt(0); }
- HValue* prototype() const { return OperandAt(1); }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- bool ObjectNeedsSmiCheck() const {
- return !object()->type().IsHeapObject() &&
- !object()->representation().IsHeapObject();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(HasInPrototypeChainAndBranch)
-
- private:
- HHasInPrototypeChainAndBranch(HValue* object, HValue* prototype) {
- SetOperandAt(0, object);
- SetOperandAt(1, prototype);
- SetDependsOnFlag(kCalls);
- }
-};
-
-
-class HPower final : public HTemplateInstruction<2> {
- public:
- static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* left, HValue* right);
-
- HValue* left() { return OperandAt(0); }
- HValue* right() const { return OperandAt(1); }
-
- Representation RequiredInputRepresentation(int index) override {
- return index == 0
- ? Representation::Double()
- : Representation::None();
- }
- Representation observed_input_representation(int index) override {
- return RequiredInputRepresentation(index);
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Power)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- private:
- HPower(HValue* left, HValue* right) {
- SetOperandAt(0, left);
- SetOperandAt(1, right);
- set_representation(Representation::Double());
- SetFlag(kUseGVN);
- SetChangesFlag(kNewSpacePromotion);
- }
-
- bool IsDeletable() const override {
- return !right()->representation().IsTagged();
- }
-};
-
-
-enum ExternalAddType {
- AddOfExternalAndTagged,
- AddOfExternalAndInt32,
- NoExternalAdd
-};
-
-
-class HAdd final : public HArithmeticBinaryOperation {
- public:
- static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* left, HValue* right,
- Strength strength = Strength::WEAK);
- static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* left, HValue* right, Strength strength,
- ExternalAddType external_add_type);
-
- // Add is only commutative if two integer values are added and not if two
- // tagged values are added (because it might be a String concatenation).
- // We also do not commute (pointer + offset).
- bool IsCommutative() const override {
- return !representation().IsTagged() && !representation().IsExternal();
- }
-
- HValue* Canonicalize() override;
-
- bool TryDecompose(DecompositionResult* decomposition) override {
- if (left()->IsInteger32Constant()) {
- decomposition->Apply(right(), left()->GetInteger32Constant());
- return true;
- } else if (right()->IsInteger32Constant()) {
- decomposition->Apply(left(), right()->GetInteger32Constant());
- return true;
- } else {
- return false;
- }
- }
-
- void RepresentationChanged(Representation to) override {
- if (to.IsTagged() &&
- (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved() ||
- left()->ToStringCanBeObserved() || right()->ToStringCanBeObserved())) {
- SetAllSideEffects();
- ClearFlag(kUseGVN);
- } else {
- ClearAllSideEffects();
- SetFlag(kUseGVN);
- }
- if (to.IsTagged()) {
- SetChangesFlag(kNewSpacePromotion);
- ClearFlag(kAllowUndefinedAsNaN);
- }
- }
-
- Representation RepresentationFromInputs() override;
-
- Representation RequiredInputRepresentation(int index) override;
-
- bool IsConsistentExternalRepresentation() {
- return left()->representation().IsExternal() &&
- ((external_add_type_ == AddOfExternalAndInt32 &&
- right()->representation().IsInteger32()) ||
- (external_add_type_ == AddOfExternalAndTagged &&
- right()->representation().IsTagged()));
- }
-
- ExternalAddType external_add_type() const { return external_add_type_; }
-
- DECLARE_CONCRETE_INSTRUCTION(Add)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- Range* InferRange(Zone* zone) override;
-
- private:
- HAdd(HValue* context, HValue* left, HValue* right, Strength strength,
- ExternalAddType external_add_type = NoExternalAdd)
- : HArithmeticBinaryOperation(context, left, right, strength),
- external_add_type_(external_add_type) {
- SetFlag(kCanOverflow);
- switch (external_add_type_) {
- case AddOfExternalAndTagged:
- DCHECK(left->representation().IsExternal());
- DCHECK(right->representation().IsTagged());
- SetDependsOnFlag(kNewSpacePromotion);
- ClearFlag(HValue::kCanOverflow);
- SetFlag(kHasNoObservableSideEffects);
- break;
-
- case NoExternalAdd:
- // This is a bit of a hack: The call to this constructor is generated
- // by a macro that also supports sub and mul, so it doesn't pass in
- // a value for external_add_type but uses the default.
- if (left->representation().IsExternal()) {
- external_add_type_ = AddOfExternalAndInt32;
- }
- break;
-
- case AddOfExternalAndInt32:
- // See comment above.
- UNREACHABLE();
- break;
- }
- }
-
- ExternalAddType external_add_type_;
-};
-
-
-class HSub final : public HArithmeticBinaryOperation {
- public:
- static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* left, HValue* right,
- Strength strength = Strength::WEAK);
-
- HValue* Canonicalize() override;
-
- bool TryDecompose(DecompositionResult* decomposition) override {
- if (right()->IsInteger32Constant()) {
- decomposition->Apply(left(), -right()->GetInteger32Constant());
- return true;
- } else {
- return false;
- }
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Sub)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- Range* InferRange(Zone* zone) override;
-
- private:
- HSub(HValue* context, HValue* left, HValue* right, Strength strength)
- : HArithmeticBinaryOperation(context, left, right, strength) {
- SetFlag(kCanOverflow);
- }
-};
-
-
-class HMul final : public HArithmeticBinaryOperation {
- public:
- static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* left, HValue* right,
- Strength strength = Strength::WEAK);
-
- static HInstruction* NewImul(Isolate* isolate, Zone* zone, HValue* context,
- HValue* left, HValue* right,
- Strength strength = Strength::WEAK) {
- HInstruction* instr =
- HMul::New(isolate, zone, context, left, right, strength);
- if (!instr->IsMul()) return instr;
- HMul* mul = HMul::cast(instr);
- // TODO(mstarzinger): Prevent bailout on minus zero for imul.
- mul->AssumeRepresentation(Representation::Integer32());
- mul->ClearFlag(HValue::kCanOverflow);
- return mul;
- }
-
- HValue* Canonicalize() override;
-
- // Only commutative if it is certain that not two objects are multiplicated.
- bool IsCommutative() const override { return !representation().IsTagged(); }
-
- virtual void UpdateRepresentation(Representation new_rep,
- HInferRepresentationPhase* h_infer,
- const char* reason) override {
- HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
- }
-
- bool MulMinusOne();
-
- DECLARE_CONCRETE_INSTRUCTION(Mul)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- Range* InferRange(Zone* zone) override;
-
- private:
- HMul(HValue* context, HValue* left, HValue* right, Strength strength)
- : HArithmeticBinaryOperation(context, left, right, strength) {
- SetFlag(kCanOverflow);
- }
-};
-
-
-class HMod final : public HArithmeticBinaryOperation {
- public:
- static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* left, HValue* right,
- Strength strength = Strength::WEAK);
-
- HValue* Canonicalize() override;
-
- virtual void UpdateRepresentation(Representation new_rep,
- HInferRepresentationPhase* h_infer,
- const char* reason) override {
- if (new_rep.IsSmi()) new_rep = Representation::Integer32();
- HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Mod)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- Range* InferRange(Zone* zone) override;
-
- private:
- HMod(HValue* context, HValue* left, HValue* right, Strength strength)
- : HArithmeticBinaryOperation(context, left, right, strength) {
- SetFlag(kCanBeDivByZero);
- SetFlag(kCanOverflow);
- SetFlag(kLeftCanBeNegative);
- }
-};
-
-
-class HDiv final : public HArithmeticBinaryOperation {
- public:
- static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* left, HValue* right,
- Strength strength = Strength::WEAK);
-
- HValue* Canonicalize() override;
-
- virtual void UpdateRepresentation(Representation new_rep,
- HInferRepresentationPhase* h_infer,
- const char* reason) override {
- if (new_rep.IsSmi()) new_rep = Representation::Integer32();
- HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Div)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- Range* InferRange(Zone* zone) override;
-
- private:
- HDiv(HValue* context, HValue* left, HValue* right, Strength strength)
- : HArithmeticBinaryOperation(context, left, right, strength) {
- SetFlag(kCanBeDivByZero);
- SetFlag(kCanOverflow);
- }
-};
-
-
-class HMathMinMax final : public HArithmeticBinaryOperation {
- public:
- enum Operation { kMathMin, kMathMax };
-
- static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* left, HValue* right, Operation op);
-
- Representation observed_input_representation(int index) override {
- return RequiredInputRepresentation(index);
- }
-
- virtual void InferRepresentation(HInferRepresentationPhase* h_infer) override;
-
- Representation RepresentationFromInputs() override {
- Representation left_rep = left()->representation();
- Representation right_rep = right()->representation();
- Representation result = Representation::Smi();
- result = result.generalize(left_rep);
- result = result.generalize(right_rep);
- if (result.IsTagged()) return Representation::Double();
- return result;
- }
-
- bool IsCommutative() const override { return true; }
-
- Operation operation() { return operation_; }
-
- DECLARE_CONCRETE_INSTRUCTION(MathMinMax)
-
- protected:
- bool DataEquals(HValue* other) override {
- return other->IsMathMinMax() &&
- HMathMinMax::cast(other)->operation_ == operation_;
- }
-
- Range* InferRange(Zone* zone) override;
-
- private:
- HMathMinMax(HValue* context, HValue* left, HValue* right, Operation op)
- : HArithmeticBinaryOperation(context, left, right, Strength::WEAK),
- operation_(op) {}
-
- Operation operation_;
-};
-
-
-class HBitwise final : public HBitwiseBinaryOperation {
- public:
- static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
- Token::Value op, HValue* left, HValue* right,
- Strength strength = Strength::WEAK);
-
- Token::Value op() const { return op_; }
-
- bool IsCommutative() const override { return true; }
-
- HValue* Canonicalize() override;
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- DECLARE_CONCRETE_INSTRUCTION(Bitwise)
-
- protected:
- bool DataEquals(HValue* other) override {
- return op() == HBitwise::cast(other)->op();
- }
-
- Range* InferRange(Zone* zone) override;
-
- private:
- HBitwise(HValue* context, Token::Value op, HValue* left, HValue* right,
- Strength strength)
- : HBitwiseBinaryOperation(context, left, right, strength), op_(op) {
- DCHECK(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR);
- // BIT_AND with a smi-range positive value will always unset the
- // entire sign-extension of the smi-sign.
- if (op == Token::BIT_AND &&
- ((left->IsConstant() &&
- left->representation().IsSmi() &&
- HConstant::cast(left)->Integer32Value() >= 0) ||
- (right->IsConstant() &&
- right->representation().IsSmi() &&
- HConstant::cast(right)->Integer32Value() >= 0))) {
- SetFlag(kTruncatingToSmi);
- SetFlag(kTruncatingToInt32);
- // BIT_OR with a smi-range negative value will always set the entire
- // sign-extension of the smi-sign.
- } else if (op == Token::BIT_OR &&
- ((left->IsConstant() &&
- left->representation().IsSmi() &&
- HConstant::cast(left)->Integer32Value() < 0) ||
- (right->IsConstant() &&
- right->representation().IsSmi() &&
- HConstant::cast(right)->Integer32Value() < 0))) {
- SetFlag(kTruncatingToSmi);
- SetFlag(kTruncatingToInt32);
- }
- }
-
- Token::Value op_;
-};
-
-
-class HShl final : public HBitwiseBinaryOperation {
- public:
- static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* left, HValue* right,
- Strength strength = Strength::WEAK);
-
- Range* InferRange(Zone* zone) override;
-
- virtual void UpdateRepresentation(Representation new_rep,
- HInferRepresentationPhase* h_infer,
- const char* reason) override {
- if (new_rep.IsSmi() &&
- !(right()->IsInteger32Constant() &&
- right()->GetInteger32Constant() >= 0)) {
- new_rep = Representation::Integer32();
- }
- HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Shl)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- private:
- HShl(HValue* context, HValue* left, HValue* right, Strength strength)
- : HBitwiseBinaryOperation(context, left, right, strength) {}
-};
-
-
-class HShr final : public HBitwiseBinaryOperation {
- public:
- static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* left, HValue* right,
- Strength strength = Strength::WEAK);
-
- bool TryDecompose(DecompositionResult* decomposition) override {
- if (right()->IsInteger32Constant()) {
- if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
- // This is intended to look for HAdd and HSub, to handle compounds
- // like ((base + offset) >> scale) with one single decomposition.
- left()->TryDecompose(decomposition);
- return true;
- }
- }
- return false;
- }
-
- Range* InferRange(Zone* zone) override;
-
- virtual void UpdateRepresentation(Representation new_rep,
- HInferRepresentationPhase* h_infer,
- const char* reason) override {
- if (new_rep.IsSmi()) new_rep = Representation::Integer32();
- HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Shr)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- private:
- HShr(HValue* context, HValue* left, HValue* right, Strength strength)
- : HBitwiseBinaryOperation(context, left, right, strength) {}
-};
-
-
-class HSar final : public HBitwiseBinaryOperation {
- public:
- static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* left, HValue* right,
- Strength strength = Strength::WEAK);
-
- bool TryDecompose(DecompositionResult* decomposition) override {
- if (right()->IsInteger32Constant()) {
- if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
- // This is intended to look for HAdd and HSub, to handle compounds
- // like ((base + offset) >> scale) with one single decomposition.
- left()->TryDecompose(decomposition);
- return true;
- }
- }
- return false;
- }
-
- Range* InferRange(Zone* zone) override;
-
- virtual void UpdateRepresentation(Representation new_rep,
- HInferRepresentationPhase* h_infer,
- const char* reason) override {
- if (new_rep.IsSmi()) new_rep = Representation::Integer32();
- HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Sar)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- private:
- HSar(HValue* context, HValue* left, HValue* right, Strength strength)
- : HBitwiseBinaryOperation(context, left, right, strength) {}
-};
-
-
-class HRor final : public HBitwiseBinaryOperation {
- public:
- static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* left, HValue* right,
- Strength strength = Strength::WEAK) {
- return new (zone) HRor(context, left, right, strength);
- }
-
- virtual void UpdateRepresentation(Representation new_rep,
- HInferRepresentationPhase* h_infer,
- const char* reason) override {
- if (new_rep.IsSmi()) new_rep = Representation::Integer32();
- HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Ror)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- private:
- HRor(HValue* context, HValue* left, HValue* right, Strength strength)
- : HBitwiseBinaryOperation(context, left, right, strength) {
- ChangeRepresentation(Representation::Integer32());
- }
-};
-
-
-class HOsrEntry final : public HTemplateInstruction<0> {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HOsrEntry, BailoutId);
-
- BailoutId ast_id() const { return ast_id_; }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(OsrEntry)
-
- private:
- explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
- SetChangesFlag(kOsrEntries);
- SetChangesFlag(kNewSpacePromotion);
- }
-
- BailoutId ast_id_;
-};
-
-
-class HParameter final : public HTemplateInstruction<0> {
- public:
- enum ParameterKind {
- STACK_PARAMETER,
- REGISTER_PARAMETER
- };
-
- DECLARE_INSTRUCTION_FACTORY_P1(HParameter, unsigned);
- DECLARE_INSTRUCTION_FACTORY_P2(HParameter, unsigned, ParameterKind);
- DECLARE_INSTRUCTION_FACTORY_P3(HParameter, unsigned, ParameterKind,
- Representation);
-
- unsigned index() const { return index_; }
- ParameterKind kind() const { return kind_; }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
-
- Representation KnownOptimalRepresentation() override {
- // If a parameter is an input to a phi, that phi should not
- // choose any more optimistic representation than Tagged.
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Parameter)
-
- private:
- explicit HParameter(unsigned index,
- ParameterKind kind = STACK_PARAMETER)
- : index_(index),
- kind_(kind) {
- set_representation(Representation::Tagged());
- }
-
- explicit HParameter(unsigned index,
- ParameterKind kind,
- Representation r)
- : index_(index),
- kind_(kind) {
- set_representation(r);
- }
-
- unsigned index_;
- ParameterKind kind_;
-};
-
-
-class HCallStub final : public HUnaryCall {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallStub, CodeStub::Major, int);
- CodeStub::Major major_key() { return major_key_; }
-
- HValue* context() { return value(); }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- DECLARE_CONCRETE_INSTRUCTION(CallStub)
-
- private:
- HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
- : HUnaryCall(context, argument_count),
- major_key_(major_key) {
- }
-
- CodeStub::Major major_key_;
-};
-
-
-class HUnknownOSRValue final : public HTemplateInstruction<0> {
- public:
- DECLARE_INSTRUCTION_FACTORY_P2(HUnknownOSRValue, HEnvironment*, int);
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::None();
- }
-
- void set_incoming_value(HPhi* value) { incoming_value_ = value; }
- HPhi* incoming_value() { return incoming_value_; }
- HEnvironment *environment() { return environment_; }
- int index() { return index_; }
-
- Representation KnownOptimalRepresentation() override {
- if (incoming_value_ == NULL) return Representation::None();
- return incoming_value_->KnownOptimalRepresentation();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
-
- private:
- HUnknownOSRValue(HEnvironment* environment, int index)
- : environment_(environment),
- index_(index),
- incoming_value_(NULL) {
- set_representation(Representation::Tagged());
- }
-
- HEnvironment* environment_;
- int index_;
- HPhi* incoming_value_;
-};
-
-
-class HLoadGlobalGeneric final : public HTemplateInstruction<2> {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HLoadGlobalGeneric, HValue*,
- Handle<String>, TypeofMode);
-
- HValue* context() { return OperandAt(0); }
- HValue* global_object() { return OperandAt(1); }
- Handle<String> name() const { return name_; }
- TypeofMode typeof_mode() const { return typeof_mode_; }
- FeedbackVectorSlot slot() const { return slot_; }
- Handle<TypeFeedbackVector> feedback_vector() const {
- return feedback_vector_;
- }
- bool HasVectorAndSlot() const { return true; }
- void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
- FeedbackVectorSlot slot) {
- feedback_vector_ = vector;
- slot_ = slot;
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric)
-
- private:
- HLoadGlobalGeneric(HValue* context, HValue* global_object,
- Handle<String> name, TypeofMode typeof_mode)
- : name_(name), typeof_mode_(typeof_mode) {
- SetOperandAt(0, context);
- SetOperandAt(1, global_object);
- set_representation(Representation::Tagged());
- SetAllSideEffects();
- }
-
- Handle<String> name_;
- TypeofMode typeof_mode_;
- Handle<TypeFeedbackVector> feedback_vector_;
- FeedbackVectorSlot slot_;
-};
-
-
-class HLoadGlobalViaContext final : public HTemplateInstruction<1> {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HLoadGlobalViaContext, int, int);
-
- HValue* context() { return OperandAt(0); }
- int depth() const { return depth_; }
- int slot_index() const { return slot_index_; }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(LoadGlobalViaContext)
-
- private:
- HLoadGlobalViaContext(HValue* context, int depth, int slot_index)
- : depth_(depth), slot_index_(slot_index) {
- SetOperandAt(0, context);
- set_representation(Representation::Tagged());
- SetAllSideEffects();
- }
-
- int const depth_;
- int const slot_index_;
-};
-
-
-class HAllocate final : public HTemplateInstruction<2> {
- public:
- static bool CompatibleInstanceTypes(InstanceType type1,
- InstanceType type2) {
- return ComputeFlags(TENURED, type1) == ComputeFlags(TENURED, type2) &&
- ComputeFlags(NOT_TENURED, type1) == ComputeFlags(NOT_TENURED, type2);
- }
-
- static HAllocate* New(
- Isolate* isolate, Zone* zone, HValue* context, HValue* size, HType type,
- PretenureFlag pretenure_flag, InstanceType instance_type,
- Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null()) {
- return new(zone) HAllocate(context, size, type, pretenure_flag,
- instance_type, allocation_site);
- }
-
- // Maximum instance size for which allocations will be inlined.
- static const int kMaxInlineSize = 64 * kPointerSize;
-
- HValue* context() const { return OperandAt(0); }
- HValue* size() const { return OperandAt(1); }
-
- bool has_size_upper_bound() { return size_upper_bound_ != NULL; }
- HConstant* size_upper_bound() { return size_upper_bound_; }
- void set_size_upper_bound(HConstant* value) {
- DCHECK(size_upper_bound_ == NULL);
- size_upper_bound_ = value;
- }
-
- Representation RequiredInputRepresentation(int index) override {
- if (index == 0) {
- return Representation::Tagged();
- } else {
- return Representation::Integer32();
- }
- }
-
- Handle<Map> GetMonomorphicJSObjectMap() override {
- return known_initial_map_;
- }
-
- void set_known_initial_map(Handle<Map> known_initial_map) {
- known_initial_map_ = known_initial_map;
- }
-
- bool IsNewSpaceAllocation() const {
- return (flags_ & ALLOCATE_IN_NEW_SPACE) != 0;
- }
-
- bool IsOldSpaceAllocation() const {
- return (flags_ & ALLOCATE_IN_OLD_SPACE) != 0;
- }
-
- bool MustAllocateDoubleAligned() const {
- return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0;
- }
-
- bool MustPrefillWithFiller() const {
- return (flags_ & PREFILL_WITH_FILLER) != 0;
- }
-
- void MakePrefillWithFiller() {
- flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER);
- }
-
- bool MustClearNextMapWord() const {
- return (flags_ & CLEAR_NEXT_MAP_WORD) != 0;
- }
-
- void MakeDoubleAligned() {
- flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED);
- }
-
- virtual bool HandleSideEffectDominator(GVNFlag side_effect,
- HValue* dominator) override;
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- DECLARE_CONCRETE_INSTRUCTION(Allocate)
-
- private:
- enum Flags {
- ALLOCATE_IN_NEW_SPACE = 1 << 0,
- ALLOCATE_IN_OLD_SPACE = 1 << 2,
- ALLOCATE_DOUBLE_ALIGNED = 1 << 3,
- PREFILL_WITH_FILLER = 1 << 4,
- CLEAR_NEXT_MAP_WORD = 1 << 5
- };
-
- HAllocate(HValue* context,
- HValue* size,
- HType type,
- PretenureFlag pretenure_flag,
- InstanceType instance_type,
- Handle<AllocationSite> allocation_site =
- Handle<AllocationSite>::null())
- : HTemplateInstruction<2>(type),
- flags_(ComputeFlags(pretenure_flag, instance_type)),
- dominating_allocate_(NULL),
- filler_free_space_size_(NULL),
- size_upper_bound_(NULL) {
- SetOperandAt(0, context);
- UpdateSize(size);
- set_representation(Representation::Tagged());
- SetFlag(kTrackSideEffectDominators);
- SetChangesFlag(kNewSpacePromotion);
- SetDependsOnFlag(kNewSpacePromotion);
-
- if (FLAG_trace_pretenuring) {
- PrintF("HAllocate with AllocationSite %p %s\n",
- allocation_site.is_null()
- ? static_cast<void*>(NULL)
- : static_cast<void*>(*allocation_site),
- pretenure_flag == TENURED ? "tenured" : "not tenured");
- }
- }
-
- static Flags ComputeFlags(PretenureFlag pretenure_flag,
- InstanceType instance_type) {
- Flags flags = pretenure_flag == TENURED ? ALLOCATE_IN_OLD_SPACE
- : ALLOCATE_IN_NEW_SPACE;
- if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
- flags = static_cast<Flags>(flags | ALLOCATE_DOUBLE_ALIGNED);
- }
- // We have to fill the allocated object with one word fillers if we do
- // not use allocation folding since some allocations may depend on each
- // other, i.e., have a pointer to each other. A GC in between these
- // allocations may leave such objects behind in a not completely initialized
- // state.
- if (!FLAG_use_gvn || !FLAG_use_allocation_folding) {
- flags = static_cast<Flags>(flags | PREFILL_WITH_FILLER);
- }
- if (pretenure_flag == NOT_TENURED &&
- AllocationSite::CanTrack(instance_type)) {
- flags = static_cast<Flags>(flags | CLEAR_NEXT_MAP_WORD);
- }
- return flags;
- }
-
- void UpdateClearNextMapWord(bool clear_next_map_word) {
- flags_ = static_cast<Flags>(clear_next_map_word
- ? flags_ | CLEAR_NEXT_MAP_WORD
- : flags_ & ~CLEAR_NEXT_MAP_WORD);
- }
-
- void UpdateSize(HValue* size) {
- SetOperandAt(1, size);
- if (size->IsInteger32Constant()) {
- size_upper_bound_ = HConstant::cast(size);
- } else {
- size_upper_bound_ = NULL;
- }
- }
-
- HAllocate* GetFoldableDominator(HAllocate* dominator);
-
- void UpdateFreeSpaceFiller(int32_t filler_size);
-
- void CreateFreeSpaceFiller(int32_t filler_size);
-
- bool IsFoldable(HAllocate* allocate) {
- return (IsNewSpaceAllocation() && allocate->IsNewSpaceAllocation()) ||
- (IsOldSpaceAllocation() && allocate->IsOldSpaceAllocation());
- }
-
- void ClearNextMapWord(int offset);
-
- Flags flags_;
- Handle<Map> known_initial_map_;
- HAllocate* dominating_allocate_;
- HStoreNamedField* filler_free_space_size_;
- HConstant* size_upper_bound_;
-};
-
-
-class HStoreCodeEntry final : public HTemplateInstruction<2> {
- public:
- static HStoreCodeEntry* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* function, HValue* code) {
- return new(zone) HStoreCodeEntry(function, code);
- }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- HValue* function() { return OperandAt(0); }
- HValue* code_object() { return OperandAt(1); }
-
- DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry)
-
- private:
- HStoreCodeEntry(HValue* function, HValue* code) {
- SetOperandAt(0, function);
- SetOperandAt(1, code);
- }
-};
-
-
-class HInnerAllocatedObject final : public HTemplateInstruction<2> {
- public:
- static HInnerAllocatedObject* New(Isolate* isolate, Zone* zone,
- HValue* context, HValue* value,
- HValue* offset, HType type) {
- return new(zone) HInnerAllocatedObject(value, offset, type);
- }
-
- HValue* base_object() const { return OperandAt(0); }
- HValue* offset() const { return OperandAt(1); }
-
- Representation RequiredInputRepresentation(int index) override {
- return index == 0 ? Representation::Tagged() : Representation::Integer32();
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject)
-
- private:
- HInnerAllocatedObject(HValue* value,
- HValue* offset,
- HType type) : HTemplateInstruction<2>(type) {
- DCHECK(value->IsAllocate());
- DCHECK(type.IsHeapObject());
- SetOperandAt(0, value);
- SetOperandAt(1, offset);
- set_representation(Representation::Tagged());
- }
-};
-
-
-inline bool StoringValueNeedsWriteBarrier(HValue* value) {
- return !value->type().IsSmi()
- && !value->type().IsNull()
- && !value->type().IsBoolean()
- && !value->type().IsUndefined()
- && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable());
-}
-
-
-inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
- HValue* value,
- HValue* dominator) {
- while (object->IsInnerAllocatedObject()) {
- object = HInnerAllocatedObject::cast(object)->base_object();
- }
- if (object->IsConstant() &&
- HConstant::cast(object)->HasExternalReferenceValue()) {
- // Stores to external references require no write barriers
- return false;
- }
- // We definitely need a write barrier unless the object is the allocation
- // dominator.
- if (object == dominator && object->IsAllocate()) {
- // Stores to new space allocations require no write barriers.
- if (HAllocate::cast(object)->IsNewSpaceAllocation()) {
- return false;
- }
- // Stores to old space allocations require no write barriers if the value is
- // a constant provably not in new space.
- if (value->IsConstant() && HConstant::cast(value)->NotInNewSpace()) {
- return false;
- }
- // Stores to old space allocations require no write barriers if the value is
- // an old space allocation.
- while (value->IsInnerAllocatedObject()) {
- value = HInnerAllocatedObject::cast(value)->base_object();
- }
- if (value->IsAllocate() &&
- !HAllocate::cast(value)->IsNewSpaceAllocation()) {
- return false;
- }
- }
- return true;
-}
-
-
-inline PointersToHereCheck PointersToHereCheckForObject(HValue* object,
- HValue* dominator) {
- while (object->IsInnerAllocatedObject()) {
- object = HInnerAllocatedObject::cast(object)->base_object();
- }
- if (object == dominator &&
- object->IsAllocate() &&
- HAllocate::cast(object)->IsNewSpaceAllocation()) {
- return kPointersToHereAreAlwaysInteresting;
- }
- return kPointersToHereMaybeInteresting;
-}
-
-
-class HLoadContextSlot final : public HUnaryOperation {
- public:
- enum Mode {
- // Perform a normal load of the context slot without checking its value.
- kNoCheck,
- // Load and check the value of the context slot. Deoptimize if it's the
- // hole value. This is used for checking for loading of uninitialized
- // harmony bindings where we deoptimize into full-codegen generated code
- // which will subsequently throw a reference error.
- kCheckDeoptimize,
- // Load and check the value of the context slot. Return undefined if it's
- // the hole value. This is used for non-harmony const assignments
- kCheckReturnUndefined
- };
-
- HLoadContextSlot(HValue* context, int slot_index, Mode mode)
- : HUnaryOperation(context), slot_index_(slot_index), mode_(mode) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetDependsOnFlag(kContextSlots);
- }
-
- int slot_index() const { return slot_index_; }
- Mode mode() const { return mode_; }
-
- bool DeoptimizesOnHole() {
- return mode_ == kCheckDeoptimize;
- }
-
- bool RequiresHoleCheck() const {
- return mode_ != kNoCheck;
- }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)
-
- protected:
- bool DataEquals(HValue* other) override {
- HLoadContextSlot* b = HLoadContextSlot::cast(other);
- return (slot_index() == b->slot_index());
- }
-
- private:
- bool IsDeletable() const override { return !RequiresHoleCheck(); }
-
- int slot_index_;
- Mode mode_;
-};
-
-
-class HStoreContextSlot final : public HTemplateInstruction<2> {
- public:
- enum Mode {
- // Perform a normal store to the context slot without checking its previous
- // value.
- kNoCheck,
- // Check the previous value of the context slot and deoptimize if it's the
- // hole value. This is used for checking for assignments to uninitialized
- // harmony bindings where we deoptimize into full-codegen generated code
- // which will subsequently throw a reference error.
- kCheckDeoptimize,
- // Check the previous value and ignore assignment if it isn't a hole value
- kCheckIgnoreAssignment
- };
-
- DECLARE_INSTRUCTION_FACTORY_P4(HStoreContextSlot, HValue*, int,
- Mode, HValue*);
-
- HValue* context() const { return OperandAt(0); }
- HValue* value() const { return OperandAt(1); }
- int slot_index() const { return slot_index_; }
- Mode mode() const { return mode_; }
-
- bool NeedsWriteBarrier() {
- return StoringValueNeedsWriteBarrier(value());
- }
-
- bool DeoptimizesOnHole() {
- return mode_ == kCheckDeoptimize;
- }
-
- bool RequiresHoleCheck() {
- return mode_ != kNoCheck;
- }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
-
- private:
- HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
- : slot_index_(slot_index), mode_(mode) {
- SetOperandAt(0, context);
- SetOperandAt(1, value);
- SetChangesFlag(kContextSlots);
- }
-
- int slot_index_;
- Mode mode_;
-};
-
-
-// Represents an access to a portion of an object, such as the map pointer,
-// array elements pointer, etc, but not accesses to array elements themselves.
-class HObjectAccess final {
- public:
- inline bool IsInobject() const {
- return portion() != kBackingStore && portion() != kExternalMemory;
- }
-
- inline bool IsExternalMemory() const {
- return portion() == kExternalMemory;
- }
-
- inline bool IsStringLength() const {
- return portion() == kStringLengths;
- }
-
- inline bool IsMap() const {
- return portion() == kMaps;
- }
-
- inline int offset() const {
- return OffsetField::decode(value_);
- }
-
- inline Representation representation() const {
- return Representation::FromKind(RepresentationField::decode(value_));
- }
-
- inline Handle<Name> name() const { return name_; }
-
- inline bool immutable() const {
- return ImmutableField::decode(value_);
- }
-
- // Returns true if access is being made to an in-object property that
- // was already added to the object.
- inline bool existing_inobject_property() const {
- return ExistingInobjectPropertyField::decode(value_);
- }
-
- inline HObjectAccess WithRepresentation(Representation representation) {
- return HObjectAccess(portion(), offset(), representation, name(),
- immutable(), existing_inobject_property());
- }
-
- static HObjectAccess ForHeapNumberValue() {
- return HObjectAccess(
- kDouble, HeapNumber::kValueOffset, Representation::Double());
- }
-
- static HObjectAccess ForHeapNumberValueLowestBits() {
- return HObjectAccess(kDouble,
- HeapNumber::kValueOffset,
- Representation::Integer32());
- }
-
- static HObjectAccess ForHeapNumberValueHighestBits() {
- return HObjectAccess(kDouble,
- HeapNumber::kValueOffset + kIntSize,
- Representation::Integer32());
- }
-
- static HObjectAccess ForOddballToNumber(
- Representation representation = Representation::Tagged()) {
- return HObjectAccess(kInobject, Oddball::kToNumberOffset, representation);
- }
-
- static HObjectAccess ForOddballTypeOf() {
- return HObjectAccess(kInobject, Oddball::kTypeOfOffset,
- Representation::HeapObject());
- }
-
- static HObjectAccess ForElementsPointer() {
- return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
- }
-
- static HObjectAccess ForLiteralsPointer() {
- return HObjectAccess(kInobject, JSFunction::kLiteralsOffset);
- }
-
- static HObjectAccess ForNextFunctionLinkPointer() {
- return HObjectAccess(kInobject, JSFunction::kNextFunctionLinkOffset);
- }
-
- static HObjectAccess ForArrayLength(ElementsKind elements_kind) {
- return HObjectAccess(
- kArrayLengths,
- JSArray::kLengthOffset,
- IsFastElementsKind(elements_kind)
- ? Representation::Smi() : Representation::Tagged());
- }
-
- static HObjectAccess ForAllocationSiteOffset(int offset);
-
- static HObjectAccess ForAllocationSiteList() {
- return HObjectAccess(kExternalMemory, 0, Representation::Tagged(),
- Handle<Name>::null(), false, false);
- }
-
- static HObjectAccess ForFixedArrayLength() {
- return HObjectAccess(
- kArrayLengths,
- FixedArray::kLengthOffset,
- Representation::Smi());
- }
-
- static HObjectAccess ForFixedTypedArrayBaseBasePointer() {
- return HObjectAccess(kInobject, FixedTypedArrayBase::kBasePointerOffset,
- Representation::Tagged());
- }
-
- static HObjectAccess ForFixedTypedArrayBaseExternalPointer() {
- return HObjectAccess::ForObservableJSObjectOffset(
- FixedTypedArrayBase::kExternalPointerOffset,
- Representation::External());
- }
-
- static HObjectAccess ForStringHashField() {
- return HObjectAccess(kInobject,
- String::kHashFieldOffset,
- Representation::Integer32());
- }
-
- static HObjectAccess ForStringLength() {
- STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
- return HObjectAccess(
- kStringLengths,
- String::kLengthOffset,
- Representation::Smi());
- }
-
- static HObjectAccess ForConsStringFirst() {
- return HObjectAccess(kInobject, ConsString::kFirstOffset);
- }
-
- static HObjectAccess ForConsStringSecond() {
- return HObjectAccess(kInobject, ConsString::kSecondOffset);
- }
-
- static HObjectAccess ForPropertiesPointer() {
- return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
- }
-
- static HObjectAccess ForPrototypeOrInitialMap() {
- return HObjectAccess(kInobject, JSFunction::kPrototypeOrInitialMapOffset);
- }
-
- static HObjectAccess ForSharedFunctionInfoPointer() {
- return HObjectAccess(kInobject, JSFunction::kSharedFunctionInfoOffset);
- }
-
- static HObjectAccess ForCodeEntryPointer() {
- return HObjectAccess(kInobject, JSFunction::kCodeEntryOffset);
- }
-
- static HObjectAccess ForCodeOffset() {
- return HObjectAccess(kInobject, SharedFunctionInfo::kCodeOffset);
- }
-
- static HObjectAccess ForOptimizedCodeMap() {
- return HObjectAccess(kInobject,
- SharedFunctionInfo::kOptimizedCodeMapOffset);
- }
-
- static HObjectAccess ForOptimizedCodeMapSharedCode() {
- return HObjectAccess(kInobject, FixedArray::OffsetOfElementAt(
- SharedFunctionInfo::kSharedCodeIndex));
- }
-
- static HObjectAccess ForFunctionContextPointer() {
- return HObjectAccess(kInobject, JSFunction::kContextOffset);
- }
-
- static HObjectAccess ForMap() {
- return HObjectAccess(kMaps, JSObject::kMapOffset);
- }
-
- static HObjectAccess ForPrototype() {
- return HObjectAccess(kMaps, Map::kPrototypeOffset);
- }
-
- static HObjectAccess ForMapAsInteger32() {
- return HObjectAccess(kMaps, JSObject::kMapOffset,
- Representation::Integer32());
- }
-
- static HObjectAccess ForMapInObjectPropertiesOrConstructorFunctionIndex() {
- return HObjectAccess(
- kInobject, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset,
- Representation::UInteger8());
- }
-
- static HObjectAccess ForMapInstanceType() {
- return HObjectAccess(kInobject,
- Map::kInstanceTypeOffset,
- Representation::UInteger8());
- }
-
- static HObjectAccess ForMapInstanceSize() {
- return HObjectAccess(kInobject,
- Map::kInstanceSizeOffset,
- Representation::UInteger8());
- }
-
- static HObjectAccess ForMapBitField() {
- return HObjectAccess(kInobject,
- Map::kBitFieldOffset,
- Representation::UInteger8());
- }
-
- static HObjectAccess ForMapBitField2() {
- return HObjectAccess(kInobject,
- Map::kBitField2Offset,
- Representation::UInteger8());
- }
-
- static HObjectAccess ForNameHashField() {
- return HObjectAccess(kInobject,
- Name::kHashFieldOffset,
- Representation::Integer32());
- }
-
- static HObjectAccess ForMapInstanceTypeAndBitField() {
- STATIC_ASSERT((Map::kInstanceTypeAndBitFieldOffset & 1) == 0);
- // Ensure the two fields share one 16-bit word, endian-independent.
- STATIC_ASSERT((Map::kBitFieldOffset & ~1) ==
- (Map::kInstanceTypeOffset & ~1));
- return HObjectAccess(kInobject,
- Map::kInstanceTypeAndBitFieldOffset,
- Representation::UInteger16());
- }
-
- static HObjectAccess ForPropertyCellValue() {
- return HObjectAccess(kInobject, PropertyCell::kValueOffset);
- }
-
- static HObjectAccess ForPropertyCellDetails() {
- return HObjectAccess(kInobject, PropertyCell::kDetailsOffset,
- Representation::Smi());
- }
-
- static HObjectAccess ForCellValue() {
- return HObjectAccess(kInobject, Cell::kValueOffset);
- }
-
- static HObjectAccess ForWeakCellValue() {
- return HObjectAccess(kInobject, WeakCell::kValueOffset);
- }
-
- static HObjectAccess ForWeakCellNext() {
- return HObjectAccess(kInobject, WeakCell::kNextOffset);
- }
-
- static HObjectAccess ForAllocationMementoSite() {
- return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset);
- }
-
- static HObjectAccess ForCounter() {
- return HObjectAccess(kExternalMemory, 0, Representation::Integer32(),
- Handle<Name>::null(), false, false);
- }
-
- static HObjectAccess ForExternalUInteger8() {
- return HObjectAccess(kExternalMemory, 0, Representation::UInteger8(),
- Handle<Name>::null(), false, false);
- }
-
- // Create an access to an offset in a fixed array header.
- static HObjectAccess ForFixedArrayHeader(int offset);
-
- // Create an access to an in-object property in a JSObject.
- // This kind of access must be used when the object |map| is known and
- // in-object properties are being accessed. Accesses of the in-object
- // properties can have different semantics depending on whether corresponding
- // property was added to the map or not.
- static HObjectAccess ForMapAndOffset(Handle<Map> map, int offset,
- Representation representation = Representation::Tagged());
-
- // Create an access to an in-object property in a JSObject.
- // This kind of access can be used for accessing object header fields or
- // in-object properties if the map of the object is not known.
- static HObjectAccess ForObservableJSObjectOffset(int offset,
- Representation representation = Representation::Tagged()) {
- return ForMapAndOffset(Handle<Map>::null(), offset, representation);
- }
-
- // Create an access to an in-object property in a JSArray.
- static HObjectAccess ForJSArrayOffset(int offset);
-
- static HObjectAccess ForContextSlot(int index);
-
- static HObjectAccess ForScriptContext(int index);
-
- // Create an access to the backing store of an object.
- static HObjectAccess ForBackingStoreOffset(int offset,
- Representation representation = Representation::Tagged());
-
- // Create an access to a resolved field (in-object or backing store).
- static HObjectAccess ForField(Handle<Map> map, int index,
- Representation representation,
- Handle<Name> name);
-
- static HObjectAccess ForJSTypedArrayLength() {
- return HObjectAccess::ForObservableJSObjectOffset(
- JSTypedArray::kLengthOffset);
- }
-
- static HObjectAccess ForJSArrayBufferBackingStore() {
- return HObjectAccess::ForObservableJSObjectOffset(
- JSArrayBuffer::kBackingStoreOffset, Representation::External());
- }
-
- static HObjectAccess ForJSArrayBufferByteLength() {
- return HObjectAccess::ForObservableJSObjectOffset(
- JSArrayBuffer::kByteLengthOffset, Representation::Tagged());
- }
-
- static HObjectAccess ForJSArrayBufferBitField() {
- return HObjectAccess::ForObservableJSObjectOffset(
- JSArrayBuffer::kBitFieldOffset, Representation::Integer32());
- }
-
- static HObjectAccess ForJSArrayBufferBitFieldSlot() {
- return HObjectAccess::ForObservableJSObjectOffset(
- JSArrayBuffer::kBitFieldSlot, Representation::Smi());
- }
-
- static HObjectAccess ForJSArrayBufferViewBuffer() {
- return HObjectAccess::ForObservableJSObjectOffset(
- JSArrayBufferView::kBufferOffset);
- }
-
- static HObjectAccess ForJSArrayBufferViewByteOffset() {
- return HObjectAccess::ForObservableJSObjectOffset(
- JSArrayBufferView::kByteOffsetOffset);
- }
-
- static HObjectAccess ForJSArrayBufferViewByteLength() {
- return HObjectAccess::ForObservableJSObjectOffset(
- JSArrayBufferView::kByteLengthOffset);
- }
-
- static HObjectAccess ForGlobalObjectNativeContext() {
- return HObjectAccess(kInobject, GlobalObject::kNativeContextOffset);
- }
-
- static HObjectAccess ForJSCollectionTable() {
- return HObjectAccess::ForObservableJSObjectOffset(
- JSCollection::kTableOffset);
- }
-
- template <typename CollectionType>
- static HObjectAccess ForOrderedHashTableNumberOfBuckets() {
- return HObjectAccess(kInobject, CollectionType::kNumberOfBucketsOffset,
- Representation::Smi());
- }
-
- template <typename CollectionType>
- static HObjectAccess ForOrderedHashTableNumberOfElements() {
- return HObjectAccess(kInobject, CollectionType::kNumberOfElementsOffset,
- Representation::Smi());
- }
-
- template <typename CollectionType>
- static HObjectAccess ForOrderedHashTableNumberOfDeletedElements() {
- return HObjectAccess(kInobject,
- CollectionType::kNumberOfDeletedElementsOffset,
- Representation::Smi());
- }
-
- template <typename CollectionType>
- static HObjectAccess ForOrderedHashTableNextTable() {
- return HObjectAccess(kInobject, CollectionType::kNextTableOffset);
- }
-
- template <typename CollectionType>
- static HObjectAccess ForOrderedHashTableBucket(int bucket) {
- return HObjectAccess(kInobject, CollectionType::kHashTableStartOffset +
- (bucket * kPointerSize),
- Representation::Smi());
- }
-
- // Access into the data table of an OrderedHashTable with a
- // known-at-compile-time bucket count.
- template <typename CollectionType, int kBucketCount>
- static HObjectAccess ForOrderedHashTableDataTableIndex(int index) {
- return HObjectAccess(kInobject, CollectionType::kHashTableStartOffset +
- (kBucketCount * kPointerSize) +
- (index * kPointerSize));
- }
-
- inline bool Equals(HObjectAccess that) const {
- return value_ == that.value_; // portion and offset must match
- }
-
- protected:
- void SetGVNFlags(HValue *instr, PropertyAccessType access_type);
-
- private:
- // internal use only; different parts of an object or array
- enum Portion {
- kMaps, // map of an object
- kArrayLengths, // the length of an array
- kStringLengths, // the length of a string
- kElementsPointer, // elements pointer
- kBackingStore, // some field in the backing store
- kDouble, // some double field
- kInobject, // some other in-object field
- kExternalMemory // some field in external memory
- };
-
- HObjectAccess() : value_(0) {}
-
- HObjectAccess(Portion portion, int offset,
- Representation representation = Representation::Tagged(),
- Handle<Name> name = Handle<Name>::null(),
- bool immutable = false, bool existing_inobject_property = true)
- : value_(PortionField::encode(portion) |
- RepresentationField::encode(representation.kind()) |
- ImmutableField::encode(immutable ? 1 : 0) |
- ExistingInobjectPropertyField::encode(
- existing_inobject_property ? 1 : 0) |
- OffsetField::encode(offset)),
- name_(name) {
- // assert that the fields decode correctly
- DCHECK(this->offset() == offset);
- DCHECK(this->portion() == portion);
- DCHECK(this->immutable() == immutable);
- DCHECK(this->existing_inobject_property() == existing_inobject_property);
- DCHECK(RepresentationField::decode(value_) == representation.kind());
- DCHECK(!this->existing_inobject_property() || IsInobject());
- }
-
- class PortionField : public BitField<Portion, 0, 3> {};
- class RepresentationField : public BitField<Representation::Kind, 3, 4> {};
- class ImmutableField : public BitField<bool, 7, 1> {};
- class ExistingInobjectPropertyField : public BitField<bool, 8, 1> {};
- class OffsetField : public BitField<int, 9, 23> {};
-
- uint32_t value_; // encodes portion, representation, immutable, and offset
- Handle<Name> name_;
-
- friend class HLoadNamedField;
- friend class HStoreNamedField;
- friend class SideEffectsTracker;
- friend std::ostream& operator<<(std::ostream& os,
- const HObjectAccess& access);
-
- inline Portion portion() const {
- return PortionField::decode(value_);
- }
-};
-
-
-std::ostream& operator<<(std::ostream& os, const HObjectAccess& access);
-
-
-class HLoadNamedField final : public HTemplateInstruction<2> {
- public:
- DECLARE_INSTRUCTION_FACTORY_P3(HLoadNamedField, HValue*,
- HValue*, HObjectAccess);
- DECLARE_INSTRUCTION_FACTORY_P5(HLoadNamedField, HValue*, HValue*,
- HObjectAccess, const UniqueSet<Map>*, HType);
-
- HValue* object() const { return OperandAt(0); }
- HValue* dependency() const {
- DCHECK(HasDependency());
- return OperandAt(1);
- }
- bool HasDependency() const { return OperandAt(0) != OperandAt(1); }
- HObjectAccess access() const { return access_; }
- Representation field_representation() const {
- return access_.representation();
- }
-
- const UniqueSet<Map>* maps() const { return maps_; }
-
- bool HasEscapingOperandAt(int index) override { return false; }
- bool HasOutOfBoundsAccess(int size) override {
- return !access().IsInobject() || access().offset() >= size;
- }
- Representation RequiredInputRepresentation(int index) override {
- if (index == 0) {
- // object must be external in case of external memory access
- return access().IsExternalMemory() ? Representation::External()
- : Representation::Tagged();
- }
- DCHECK(index == 1);
- return Representation::None();
- }
- Range* InferRange(Zone* zone) override;
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- bool CanBeReplacedWith(HValue* other) const {
- if (!CheckFlag(HValue::kCantBeReplaced)) return false;
- if (!type().Equals(other->type())) return false;
- if (!representation().Equals(other->representation())) return false;
- if (!other->IsLoadNamedField()) return true;
- HLoadNamedField* that = HLoadNamedField::cast(other);
- if (this->maps_ == that->maps_) return true;
- if (this->maps_ == NULL || that->maps_ == NULL) return false;
- return this->maps_->IsSubset(that->maps_);
- }
-
- DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
-
- protected:
- bool DataEquals(HValue* other) override {
- HLoadNamedField* that = HLoadNamedField::cast(other);
- if (!this->access_.Equals(that->access_)) return false;
- if (this->maps_ == that->maps_) return true;
- return (this->maps_ != NULL &&
- that->maps_ != NULL &&
- this->maps_->Equals(that->maps_));
- }
-
- private:
- HLoadNamedField(HValue* object,
- HValue* dependency,
- HObjectAccess access)
- : access_(access), maps_(NULL) {
- DCHECK_NOT_NULL(object);
- SetOperandAt(0, object);
- SetOperandAt(1, dependency ? dependency : object);
-
- Representation representation = access.representation();
- if (representation.IsInteger8() ||
- representation.IsUInteger8() ||
- representation.IsInteger16() ||
- representation.IsUInteger16()) {
- set_representation(Representation::Integer32());
- } else if (representation.IsSmi()) {
- set_type(HType::Smi());
- if (SmiValuesAre32Bits()) {
- set_representation(Representation::Integer32());
- } else {
- set_representation(representation);
- }
- } else if (representation.IsDouble() ||
- representation.IsExternal() ||
- representation.IsInteger32()) {
- set_representation(representation);
- } else if (representation.IsHeapObject()) {
- set_type(HType::HeapObject());
- set_representation(Representation::Tagged());
- } else {
- set_representation(Representation::Tagged());
- }
- access.SetGVNFlags(this, LOAD);
- }
-
- HLoadNamedField(HValue* object,
- HValue* dependency,
- HObjectAccess access,
- const UniqueSet<Map>* maps,
- HType type)
- : HTemplateInstruction<2>(type), access_(access), maps_(maps) {
- DCHECK_NOT_NULL(maps);
- DCHECK_NE(0, maps->size());
-
- DCHECK_NOT_NULL(object);
- SetOperandAt(0, object);
- SetOperandAt(1, dependency ? dependency : object);
-
- DCHECK(access.representation().IsHeapObject());
- DCHECK(type.IsHeapObject());
- set_representation(Representation::Tagged());
-
- access.SetGVNFlags(this, LOAD);
- }
-
- bool IsDeletable() const override { return true; }
-
- HObjectAccess access_;
- const UniqueSet<Map>* maps_;
-};
-
-
-class HLoadNamedGeneric final : public HTemplateInstruction<2> {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HLoadNamedGeneric, HValue*,
- Handle<Name>, LanguageMode,
- InlineCacheState);
-
- HValue* context() const { return OperandAt(0); }
- HValue* object() const { return OperandAt(1); }
- Handle<Name> name() const { return name_; }
-
- InlineCacheState initialization_state() const {
- return initialization_state_;
- }
- FeedbackVectorSlot slot() const { return slot_; }
- Handle<TypeFeedbackVector> feedback_vector() const {
- return feedback_vector_;
- }
- bool HasVectorAndSlot() const { return true; }
- void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
- FeedbackVectorSlot slot) {
- feedback_vector_ = vector;
- slot_ = slot;
- }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
-
- LanguageMode language_mode() const { return language_mode_; }
-
- private:
- HLoadNamedGeneric(HValue* context, HValue* object, Handle<Name> name,
- LanguageMode language_mode,
- InlineCacheState initialization_state)
- : name_(name),
- language_mode_(language_mode),
- initialization_state_(initialization_state) {
- SetOperandAt(0, context);
- SetOperandAt(1, object);
- set_representation(Representation::Tagged());
- SetAllSideEffects();
- }
-
- Handle<Name> name_;
- Handle<TypeFeedbackVector> feedback_vector_;
- FeedbackVectorSlot slot_;
- LanguageMode language_mode_;
- InlineCacheState initialization_state_;
-};
-
-
-class HLoadFunctionPrototype final : public HUnaryOperation {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HLoadFunctionPrototype, HValue*);
-
- HValue* function() { return OperandAt(0); }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- private:
- explicit HLoadFunctionPrototype(HValue* function)
- : HUnaryOperation(function) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetDependsOnFlag(kCalls);
- }
-};
-
-class ArrayInstructionInterface {
- public:
- virtual HValue* GetKey() = 0;
- virtual void SetKey(HValue* key) = 0;
- virtual ElementsKind elements_kind() const = 0;
- // TryIncreaseBaseOffset returns false if overflow would result.
- virtual bool TryIncreaseBaseOffset(uint32_t increase_by_value) = 0;
- virtual bool IsDehoisted() const = 0;
- virtual void SetDehoisted(bool is_dehoisted) = 0;
- virtual ~ArrayInstructionInterface() { }
-
- static Representation KeyedAccessIndexRequirement(Representation r) {
- return r.IsInteger32() || SmiValuesAre32Bits()
- ? Representation::Integer32() : Representation::Smi();
- }
-};
-
-
-static const int kDefaultKeyedHeaderOffsetSentinel = -1;
-
-enum LoadKeyedHoleMode {
- NEVER_RETURN_HOLE,
- ALLOW_RETURN_HOLE,
- CONVERT_HOLE_TO_UNDEFINED
-};
-
-
-class HLoadKeyed final : public HTemplateInstruction<3>,
- public ArrayInstructionInterface {
- public:
- DECLARE_INSTRUCTION_FACTORY_P4(HLoadKeyed, HValue*, HValue*, HValue*,
- ElementsKind);
- DECLARE_INSTRUCTION_FACTORY_P5(HLoadKeyed, HValue*, HValue*, HValue*,
- ElementsKind, LoadKeyedHoleMode);
- DECLARE_INSTRUCTION_FACTORY_P6(HLoadKeyed, HValue*, HValue*, HValue*,
- ElementsKind, LoadKeyedHoleMode, int);
-
- bool is_fixed_typed_array() const {
- return IsFixedTypedArrayElementsKind(elements_kind());
- }
- HValue* elements() const { return OperandAt(0); }
- HValue* key() const { return OperandAt(1); }
- HValue* dependency() const {
- DCHECK(HasDependency());
- return OperandAt(2);
- }
- bool HasDependency() const { return OperandAt(0) != OperandAt(2); }
- uint32_t base_offset() const { return BaseOffsetField::decode(bit_field_); }
- bool TryIncreaseBaseOffset(uint32_t increase_by_value) override;
- HValue* GetKey() override { return key(); }
- void SetKey(HValue* key) override { SetOperandAt(1, key); }
- bool IsDehoisted() const override {
- return IsDehoistedField::decode(bit_field_);
- }
- void SetDehoisted(bool is_dehoisted) override {
- bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
- }
- ElementsKind elements_kind() const override {
- return ElementsKindField::decode(bit_field_);
- }
- LoadKeyedHoleMode hole_mode() const {
- return HoleModeField::decode(bit_field_);
- }
-
- Representation RequiredInputRepresentation(int index) override {
- // kind_fast: tagged[int32] (none)
- // kind_double: tagged[int32] (none)
- // kind_fixed_typed_array: external[int32] (none)
- // kind_external: external[int32] (none)
- if (index == 0) {
- return is_fixed_typed_array() ? Representation::External()
- : Representation::Tagged();
- }
- if (index == 1) {
- return ArrayInstructionInterface::KeyedAccessIndexRequirement(
- OperandAt(1)->representation());
- }
- return Representation::None();
- }
-
- Representation observed_input_representation(int index) override {
- return RequiredInputRepresentation(index);
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- bool UsesMustHandleHole() const;
- bool AllUsesCanTreatHoleAsNaN() const;
- bool RequiresHoleCheck() const;
-
- Range* InferRange(Zone* zone) override;
-
- DECLARE_CONCRETE_INSTRUCTION(LoadKeyed)
-
- protected:
- bool DataEquals(HValue* other) override {
- if (!other->IsLoadKeyed()) return false;
- HLoadKeyed* other_load = HLoadKeyed::cast(other);
-
- if (base_offset() != other_load->base_offset()) return false;
- return elements_kind() == other_load->elements_kind();
- }
-
- private:
- HLoadKeyed(HValue* obj, HValue* key, HValue* dependency,
- ElementsKind elements_kind,
- LoadKeyedHoleMode mode = NEVER_RETURN_HOLE,
- int offset = kDefaultKeyedHeaderOffsetSentinel)
- : bit_field_(0) {
- offset = offset == kDefaultKeyedHeaderOffsetSentinel
- ? GetDefaultHeaderSizeForElementsKind(elements_kind)
- : offset;
- bit_field_ = ElementsKindField::encode(elements_kind) |
- HoleModeField::encode(mode) |
- BaseOffsetField::encode(offset);
-
- SetOperandAt(0, obj);
- SetOperandAt(1, key);
- SetOperandAt(2, dependency != NULL ? dependency : obj);
-
- if (!is_fixed_typed_array()) {
- // I can detect the case between storing double (holey and fast) and
- // smi/object by looking at elements_kind_.
- DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
- IsFastDoubleElementsKind(elements_kind));
-
- if (IsFastSmiOrObjectElementsKind(elements_kind)) {
- if (IsFastSmiElementsKind(elements_kind) &&
- (!IsHoleyElementsKind(elements_kind) ||
- mode == NEVER_RETURN_HOLE)) {
- set_type(HType::Smi());
- if (SmiValuesAre32Bits() && !RequiresHoleCheck()) {
- set_representation(Representation::Integer32());
- } else {
- set_representation(Representation::Smi());
- }
- } else {
- set_representation(Representation::Tagged());
- }
-
- SetDependsOnFlag(kArrayElements);
- } else {
- set_representation(Representation::Double());
- SetDependsOnFlag(kDoubleArrayElements);
- }
- } else {
- if (elements_kind == FLOAT32_ELEMENTS ||
- elements_kind == FLOAT64_ELEMENTS) {
- set_representation(Representation::Double());
- } else {
- set_representation(Representation::Integer32());
- }
-
- if (is_fixed_typed_array()) {
- SetDependsOnFlag(kExternalMemory);
- SetDependsOnFlag(kTypedArrayElements);
- } else {
- UNREACHABLE();
- }
- // Native code could change the specialized array.
- SetDependsOnFlag(kCalls);
- }
-
- SetFlag(kUseGVN);
- }
-
- bool IsDeletable() const override { return !RequiresHoleCheck(); }
-
- // Establish some checks around our packed fields
- enum LoadKeyedBits {
- kBitsForElementsKind = 5,
- kBitsForHoleMode = 2,
- kBitsForBaseOffset = 24,
- kBitsForIsDehoisted = 1,
-
- kStartElementsKind = 0,
- kStartHoleMode = kStartElementsKind + kBitsForElementsKind,
- kStartBaseOffset = kStartHoleMode + kBitsForHoleMode,
- kStartIsDehoisted = kStartBaseOffset + kBitsForBaseOffset
- };
-
- STATIC_ASSERT((kBitsForElementsKind + kBitsForHoleMode + kBitsForBaseOffset +
- kBitsForIsDehoisted) <= sizeof(uint32_t) * 8);
- STATIC_ASSERT(kElementsKindCount <= (1 << kBitsForElementsKind));
- class ElementsKindField:
- public BitField<ElementsKind, kStartElementsKind, kBitsForElementsKind>
- {}; // NOLINT
- class HoleModeField:
- public BitField<LoadKeyedHoleMode, kStartHoleMode, kBitsForHoleMode>
- {}; // NOLINT
- class BaseOffsetField:
- public BitField<uint32_t, kStartBaseOffset, kBitsForBaseOffset>
- {}; // NOLINT
- class IsDehoistedField:
- public BitField<bool, kStartIsDehoisted, kBitsForIsDehoisted>
- {}; // NOLINT
- uint32_t bit_field_;
-};
-
-
-class HLoadKeyedGeneric final : public HTemplateInstruction<3> {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HLoadKeyedGeneric, HValue*,
- HValue*, LanguageMode,
- InlineCacheState);
- HValue* object() const { return OperandAt(0); }
- HValue* key() const { return OperandAt(1); }
- HValue* context() const { return OperandAt(2); }
- InlineCacheState initialization_state() const {
- return initialization_state_;
- }
- FeedbackVectorSlot slot() const { return slot_; }
- Handle<TypeFeedbackVector> feedback_vector() const {
- return feedback_vector_;
- }
- bool HasVectorAndSlot() const {
- DCHECK(initialization_state_ == MEGAMORPHIC || !feedback_vector_.is_null());
- return !feedback_vector_.is_null();
- }
- void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
- FeedbackVectorSlot slot) {
- feedback_vector_ = vector;
- slot_ = slot;
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- Representation RequiredInputRepresentation(int index) override {
- // tagged[tagged]
- return Representation::Tagged();
- }
-
- HValue* Canonicalize() override;
-
- DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric)
-
- LanguageMode language_mode() const { return language_mode_; }
-
- private:
- HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key,
- LanguageMode language_mode,
- InlineCacheState initialization_state)
- : initialization_state_(initialization_state),
- language_mode_(language_mode) {
- set_representation(Representation::Tagged());
- SetOperandAt(0, obj);
- SetOperandAt(1, key);
- SetOperandAt(2, context);
- SetAllSideEffects();
- }
-
- Handle<TypeFeedbackVector> feedback_vector_;
- FeedbackVectorSlot slot_;
- InlineCacheState initialization_state_;
- LanguageMode language_mode_;
-};
-
-
-// Indicates whether the store is a store to an entry that was previously
-// initialized or not.
-enum StoreFieldOrKeyedMode {
- // The entry could be either previously initialized or not.
- INITIALIZING_STORE,
- // At the time of this store it is guaranteed that the entry is already
- // initialized.
- STORE_TO_INITIALIZED_ENTRY
-};
-
-
-class HStoreNamedField final : public HTemplateInstruction<3> {
- public:
- DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*,
- HObjectAccess, HValue*);
- DECLARE_INSTRUCTION_FACTORY_P4(HStoreNamedField, HValue*,
- HObjectAccess, HValue*, StoreFieldOrKeyedMode);
-
- DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
-
- bool HasEscapingOperandAt(int index) override { return index == 1; }
- bool HasOutOfBoundsAccess(int size) override {
- return !access().IsInobject() || access().offset() >= size;
- }
- Representation RequiredInputRepresentation(int index) override {
- if (index == 0 && access().IsExternalMemory()) {
- // object must be external in case of external memory access
- return Representation::External();
- } else if (index == 1) {
- if (field_representation().IsInteger8() ||
- field_representation().IsUInteger8() ||
- field_representation().IsInteger16() ||
- field_representation().IsUInteger16() ||
- field_representation().IsInteger32()) {
- return Representation::Integer32();
- } else if (field_representation().IsDouble()) {
- return field_representation();
- } else if (field_representation().IsSmi()) {
- if (SmiValuesAre32Bits() &&
- store_mode() == STORE_TO_INITIALIZED_ENTRY) {
- return Representation::Integer32();
- }
- return field_representation();
- } else if (field_representation().IsExternal()) {
- return Representation::External();
- }
- }
- return Representation::Tagged();
- }
- virtual bool HandleSideEffectDominator(GVNFlag side_effect,
- HValue* dominator) override {
- DCHECK(side_effect == kNewSpacePromotion);
- if (!FLAG_use_write_barrier_elimination) return false;
- dominator_ = dominator;
- return false;
- }
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- HValue* object() const { return OperandAt(0); }
- HValue* value() const { return OperandAt(1); }
- HValue* transition() const { return OperandAt(2); }
-
- HObjectAccess access() const { return access_; }
- HValue* dominator() const { return dominator_; }
- bool has_transition() const { return HasTransitionField::decode(bit_field_); }
- StoreFieldOrKeyedMode store_mode() const {
- return StoreModeField::decode(bit_field_);
- }
-
- Handle<Map> transition_map() const {
- if (has_transition()) {
- return Handle<Map>::cast(
- HConstant::cast(transition())->handle(isolate()));
- } else {
- return Handle<Map>();
- }
- }
-
- void SetTransition(HConstant* transition) {
- DCHECK(!has_transition()); // Only set once.
- SetOperandAt(2, transition);
- bit_field_ = HasTransitionField::update(bit_field_, true);
- SetChangesFlag(kMaps);
- }
-
- bool NeedsWriteBarrier() const {
- DCHECK(!field_representation().IsDouble() ||
- (FLAG_unbox_double_fields && access_.IsInobject()) ||
- !has_transition());
- if (field_representation().IsDouble()) return false;
- if (field_representation().IsSmi()) return false;
- if (field_representation().IsInteger32()) return false;
- if (field_representation().IsExternal()) return false;
- return StoringValueNeedsWriteBarrier(value()) &&
- ReceiverObjectNeedsWriteBarrier(object(), value(), dominator());
- }
-
- bool NeedsWriteBarrierForMap() {
- return ReceiverObjectNeedsWriteBarrier(object(), transition(),
- dominator());
- }
-
- SmiCheck SmiCheckForWriteBarrier() const {
- if (field_representation().IsHeapObject()) return OMIT_SMI_CHECK;
- if (value()->type().IsHeapObject()) return OMIT_SMI_CHECK;
- return INLINE_SMI_CHECK;
- }
-
- PointersToHereCheck PointersToHereCheckForValue() const {
- return PointersToHereCheckForObject(value(), dominator());
- }
-
- Representation field_representation() const {
- return access_.representation();
- }
-
- void UpdateValue(HValue* value) {
- SetOperandAt(1, value);
- }
-
- bool CanBeReplacedWith(HStoreNamedField* that) const {
- if (!this->access().Equals(that->access())) return false;
- if (SmiValuesAre32Bits() &&
- this->field_representation().IsSmi() &&
- this->store_mode() == INITIALIZING_STORE &&
- that->store_mode() == STORE_TO_INITIALIZED_ENTRY) {
- // We cannot replace an initializing store to a smi field with a store to
- // an initialized entry on 64-bit architectures (with 32-bit smis).
- return false;
- }
- return true;
- }
-
- private:
- HStoreNamedField(HValue* obj, HObjectAccess access, HValue* val,
- StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE)
- : access_(access),
- dominator_(NULL),
- bit_field_(HasTransitionField::encode(false) |
- StoreModeField::encode(store_mode)) {
- // Stores to a non existing in-object property are allowed only to the
- // newly allocated objects (via HAllocate or HInnerAllocatedObject).
- DCHECK(!access.IsInobject() || access.existing_inobject_property() ||
- obj->IsAllocate() || obj->IsInnerAllocatedObject());
- SetOperandAt(0, obj);
- SetOperandAt(1, val);
- SetOperandAt(2, obj);
- access.SetGVNFlags(this, STORE);
- }
-
- class HasTransitionField : public BitField<bool, 0, 1> {};
- class StoreModeField : public BitField<StoreFieldOrKeyedMode, 1, 1> {};
-
- HObjectAccess access_;
- HValue* dominator_;
- uint32_t bit_field_;
-};
-
-
-class HStoreNamedGeneric final : public HTemplateInstruction<3> {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(HStoreNamedGeneric, HValue*,
- Handle<Name>, HValue*,
- LanguageMode, InlineCacheState);
- HValue* object() const { return OperandAt(0); }
- HValue* value() const { return OperandAt(1); }
- HValue* context() const { return OperandAt(2); }
- Handle<Name> name() const { return name_; }
- LanguageMode language_mode() const { return language_mode_; }
- InlineCacheState initialization_state() const {
- return initialization_state_;
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- FeedbackVectorSlot slot() const { return slot_; }
- Handle<TypeFeedbackVector> feedback_vector() const {
- return feedback_vector_;
- }
- bool HasVectorAndSlot() const { return FLAG_vector_stores; }
- void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
- FeedbackVectorSlot slot) {
- feedback_vector_ = vector;
- slot_ = slot;
- }
-
- DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric)
-
- private:
- HStoreNamedGeneric(HValue* context, HValue* object, Handle<Name> name,
- HValue* value, LanguageMode language_mode,
- InlineCacheState initialization_state)
- : name_(name),
- language_mode_(language_mode),
- initialization_state_(initialization_state) {
- SetOperandAt(0, object);
- SetOperandAt(1, value);
- SetOperandAt(2, context);
- SetAllSideEffects();
- }
-
- Handle<Name> name_;
- Handle<TypeFeedbackVector> feedback_vector_;
- FeedbackVectorSlot slot_;
- LanguageMode language_mode_;
- InlineCacheState initialization_state_;
-};
-
-
-class HStoreGlobalViaContext final : public HTemplateInstruction<2> {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HStoreGlobalViaContext, HValue*,
- int, int, LanguageMode);
- HValue* context() const { return OperandAt(0); }
- HValue* value() const { return OperandAt(1); }
- int depth() const { return depth_; }
- int slot_index() const { return slot_index_; }
- LanguageMode language_mode() const { return language_mode_; }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(StoreGlobalViaContext)
-
- private:
- HStoreGlobalViaContext(HValue* context, HValue* value, int depth,
- int slot_index, LanguageMode language_mode)
- : depth_(depth), slot_index_(slot_index), language_mode_(language_mode) {
- SetOperandAt(0, context);
- SetOperandAt(1, value);
- SetAllSideEffects();
- }
-
- int const depth_;
- int const slot_index_;
- LanguageMode const language_mode_;
-};
-
-
-class HStoreKeyed final : public HTemplateInstruction<3>,
- public ArrayInstructionInterface {
- public:
- DECLARE_INSTRUCTION_FACTORY_P4(HStoreKeyed, HValue*, HValue*, HValue*,
- ElementsKind);
- DECLARE_INSTRUCTION_FACTORY_P5(HStoreKeyed, HValue*, HValue*, HValue*,
- ElementsKind, StoreFieldOrKeyedMode);
- DECLARE_INSTRUCTION_FACTORY_P6(HStoreKeyed, HValue*, HValue*, HValue*,
- ElementsKind, StoreFieldOrKeyedMode, int);
-
- Representation RequiredInputRepresentation(int index) override {
- // kind_fast: tagged[int32] = tagged
- // kind_double: tagged[int32] = double
- // kind_smi : tagged[int32] = smi
- // kind_fixed_typed_array: tagged[int32] = (double | int32)
- // kind_external: external[int32] = (double | int32)
- if (index == 0) {
- return is_fixed_typed_array() ? Representation::External()
- : Representation::Tagged();
- } else if (index == 1) {
- return ArrayInstructionInterface::KeyedAccessIndexRequirement(
- OperandAt(1)->representation());
- }
-
- DCHECK_EQ(index, 2);
- return RequiredValueRepresentation(elements_kind(), store_mode());
- }
-
- static Representation RequiredValueRepresentation(
- ElementsKind kind, StoreFieldOrKeyedMode mode) {
- if (IsDoubleOrFloatElementsKind(kind)) {
- return Representation::Double();
- }
-
- if (kind == FAST_SMI_ELEMENTS && SmiValuesAre32Bits() &&
- mode == STORE_TO_INITIALIZED_ENTRY) {
- return Representation::Integer32();
- }
-
- if (IsFastSmiElementsKind(kind)) {
- return Representation::Smi();
- }
-
- if (IsFixedTypedArrayElementsKind(kind)) {
- return Representation::Integer32();
- }
- return Representation::Tagged();
- }
-
- bool is_fixed_typed_array() const {
- return IsFixedTypedArrayElementsKind(elements_kind());
- }
-
- Representation observed_input_representation(int index) override {
- if (index < 2) return RequiredInputRepresentation(index);
- if (IsUninitialized()) {
- return Representation::None();
- }
- Representation r =
- RequiredValueRepresentation(elements_kind(), store_mode());
- // For fast object elements kinds, don't assume anything.
- if (r.IsTagged()) return Representation::None();
- return r;
- }
-
- HValue* elements() const { return OperandAt(0); }
- HValue* key() const { return OperandAt(1); }
- HValue* value() const { return OperandAt(2); }
- bool value_is_smi() const { return IsFastSmiElementsKind(elements_kind()); }
- StoreFieldOrKeyedMode store_mode() const {
- return StoreModeField::decode(bit_field_);
- }
- ElementsKind elements_kind() const override {
- return ElementsKindField::decode(bit_field_);
- }
- uint32_t base_offset() const { return base_offset_; }
- bool TryIncreaseBaseOffset(uint32_t increase_by_value) override;
- HValue* GetKey() override { return key(); }
- void SetKey(HValue* key) override { SetOperandAt(1, key); }
- bool IsDehoisted() const override {
- return IsDehoistedField::decode(bit_field_);
- }
- void SetDehoisted(bool is_dehoisted) override {
- bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
- }
- bool IsUninitialized() { return IsUninitializedField::decode(bit_field_); }
- void SetUninitialized(bool is_uninitialized) {
- bit_field_ = IsUninitializedField::update(bit_field_, is_uninitialized);
- }
-
- bool IsConstantHoleStore() {
- return value()->IsConstant() && HConstant::cast(value())->IsTheHole();
- }
-
- virtual bool HandleSideEffectDominator(GVNFlag side_effect,
- HValue* dominator) override {
- DCHECK(side_effect == kNewSpacePromotion);
- dominator_ = dominator;
- return false;
- }
-
- HValue* dominator() const { return dominator_; }
-
- bool NeedsWriteBarrier() {
- if (value_is_smi()) {
- return false;
- } else {
- return StoringValueNeedsWriteBarrier(value()) &&
- ReceiverObjectNeedsWriteBarrier(elements(), value(), dominator());
- }
- }
-
- PointersToHereCheck PointersToHereCheckForValue() const {
- return PointersToHereCheckForObject(value(), dominator());
- }
-
- bool NeedsCanonicalization();
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)
-
- private:
- HStoreKeyed(HValue* obj, HValue* key, HValue* val, ElementsKind elements_kind,
- StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE,
- int offset = kDefaultKeyedHeaderOffsetSentinel)
- : base_offset_(offset == kDefaultKeyedHeaderOffsetSentinel
- ? GetDefaultHeaderSizeForElementsKind(elements_kind)
- : offset),
- bit_field_(IsDehoistedField::encode(false) |
- IsUninitializedField::encode(false) |
- StoreModeField::encode(store_mode) |
- ElementsKindField::encode(elements_kind)),
- dominator_(NULL) {
- SetOperandAt(0, obj);
- SetOperandAt(1, key);
- SetOperandAt(2, val);
-
- if (IsFastObjectElementsKind(elements_kind)) {
- SetFlag(kTrackSideEffectDominators);
- SetDependsOnFlag(kNewSpacePromotion);
- }
- if (IsFastDoubleElementsKind(elements_kind)) {
- SetChangesFlag(kDoubleArrayElements);
- } else if (IsFastSmiElementsKind(elements_kind)) {
- SetChangesFlag(kArrayElements);
- } else if (is_fixed_typed_array()) {
- SetChangesFlag(kTypedArrayElements);
- SetChangesFlag(kExternalMemory);
- SetFlag(kAllowUndefinedAsNaN);
- } else {
- SetChangesFlag(kArrayElements);
- }
-
- // {UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
- if (elements_kind >= UINT8_ELEMENTS && elements_kind <= INT32_ELEMENTS) {
- SetFlag(kTruncatingToInt32);
- }
- }
-
- class IsDehoistedField : public BitField<bool, 0, 1> {};
- class IsUninitializedField : public BitField<bool, 1, 1> {};
- class StoreModeField : public BitField<StoreFieldOrKeyedMode, 2, 1> {};
- class ElementsKindField : public BitField<ElementsKind, 3, 5> {};
-
- uint32_t base_offset_;
- uint32_t bit_field_;
- HValue* dominator_;
-};
-
-
-class HStoreKeyedGeneric final : public HTemplateInstruction<4> {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(HStoreKeyedGeneric, HValue*,
- HValue*, HValue*, LanguageMode,
- InlineCacheState);
-
- HValue* object() const { return OperandAt(0); }
- HValue* key() const { return OperandAt(1); }
- HValue* value() const { return OperandAt(2); }
- HValue* context() const { return OperandAt(3); }
- LanguageMode language_mode() const { return language_mode_; }
- InlineCacheState initialization_state() const {
- return initialization_state_;
- }
-
- Representation RequiredInputRepresentation(int index) override {
- // tagged[tagged] = tagged
- return Representation::Tagged();
- }
-
- FeedbackVectorSlot slot() const { return slot_; }
- Handle<TypeFeedbackVector> feedback_vector() const {
- return feedback_vector_;
- }
- bool HasVectorAndSlot() const {
- DCHECK(!(FLAG_vector_stores && initialization_state_ != MEGAMORPHIC) ||
- !feedback_vector_.is_null());
- return !feedback_vector_.is_null();
- }
- void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
- FeedbackVectorSlot slot) {
- feedback_vector_ = vector;
- slot_ = slot;
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric)
-
- private:
- HStoreKeyedGeneric(HValue* context, HValue* object, HValue* key,
- HValue* value, LanguageMode language_mode,
- InlineCacheState initialization_state)
- : language_mode_(language_mode),
- initialization_state_(initialization_state) {
- SetOperandAt(0, object);
- SetOperandAt(1, key);
- SetOperandAt(2, value);
- SetOperandAt(3, context);
- SetAllSideEffects();
- }
-
- Handle<TypeFeedbackVector> feedback_vector_;
- FeedbackVectorSlot slot_;
- LanguageMode language_mode_;
- InlineCacheState initialization_state_;
-};
-
-
-class HTransitionElementsKind final : public HTemplateInstruction<2> {
- public:
- inline static HTransitionElementsKind* New(Isolate* isolate, Zone* zone,
- HValue* context, HValue* object,
- Handle<Map> original_map,
- Handle<Map> transitioned_map) {
- return new(zone) HTransitionElementsKind(context, object,
- original_map, transitioned_map);
- }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- HValue* object() const { return OperandAt(0); }
- HValue* context() const { return OperandAt(1); }
- Unique<Map> original_map() const { return original_map_; }
- Unique<Map> transitioned_map() const { return transitioned_map_; }
- ElementsKind from_kind() const {
- return FromElementsKindField::decode(bit_field_);
- }
- ElementsKind to_kind() const {
- return ToElementsKindField::decode(bit_field_);
- }
- bool map_is_stable() const { return MapIsStableField::decode(bit_field_); }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
-
- protected:
- bool DataEquals(HValue* other) override {
- HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
- return original_map_ == instr->original_map_ &&
- transitioned_map_ == instr->transitioned_map_;
- }
-
- int RedefinedOperandIndex() override { return 0; }
-
- private:
- HTransitionElementsKind(HValue* context, HValue* object,
- Handle<Map> original_map,
- Handle<Map> transitioned_map)
- : original_map_(Unique<Map>(original_map)),
- transitioned_map_(Unique<Map>(transitioned_map)),
- bit_field_(
- FromElementsKindField::encode(original_map->elements_kind()) |
- ToElementsKindField::encode(transitioned_map->elements_kind()) |
- MapIsStableField::encode(transitioned_map->is_stable())) {
- SetOperandAt(0, object);
- SetOperandAt(1, context);
- SetFlag(kUseGVN);
- SetChangesFlag(kElementsKind);
- if (!IsSimpleMapChangeTransition(from_kind(), to_kind())) {
- SetChangesFlag(kElementsPointer);
- SetChangesFlag(kNewSpacePromotion);
- }
- set_representation(Representation::Tagged());
- }
-
- class FromElementsKindField : public BitField<ElementsKind, 0, 5> {};
- class ToElementsKindField : public BitField<ElementsKind, 5, 5> {};
- class MapIsStableField : public BitField<bool, 10, 1> {};
-
- Unique<Map> original_map_;
- Unique<Map> transitioned_map_;
- uint32_t bit_field_;
-};
-
-
-class HStringAdd final : public HBinaryOperation {
- public:
- static HInstruction* New(
- Isolate* isolate, Zone* zone, HValue* context, HValue* left,
- HValue* right, PretenureFlag pretenure_flag = NOT_TENURED,
- StringAddFlags flags = STRING_ADD_CHECK_BOTH,
- Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null());
-
- StringAddFlags flags() const { return flags_; }
- PretenureFlag pretenure_flag() const { return pretenure_flag_; }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- DECLARE_CONCRETE_INSTRUCTION(StringAdd)
-
- protected:
- bool DataEquals(HValue* other) override {
- return flags_ == HStringAdd::cast(other)->flags_ &&
- pretenure_flag_ == HStringAdd::cast(other)->pretenure_flag_;
- }
-
- private:
- HStringAdd(HValue* context, HValue* left, HValue* right,
- PretenureFlag pretenure_flag, StringAddFlags flags,
- Handle<AllocationSite> allocation_site)
- : HBinaryOperation(context, left, right, Strength::WEAK, HType::String()),
- flags_(flags),
- pretenure_flag_(pretenure_flag) {
- set_representation(Representation::Tagged());
- if ((flags & STRING_ADD_CONVERT) == STRING_ADD_CONVERT) {
- SetAllSideEffects();
- ClearFlag(kUseGVN);
- } else {
- SetChangesFlag(kNewSpacePromotion);
- SetFlag(kUseGVN);
- }
- SetDependsOnFlag(kMaps);
- if (FLAG_trace_pretenuring) {
- PrintF("HStringAdd with AllocationSite %p %s\n",
- allocation_site.is_null()
- ? static_cast<void*>(NULL)
- : static_cast<void*>(*allocation_site),
- pretenure_flag == TENURED ? "tenured" : "not tenured");
- }
- }
-
- bool IsDeletable() const final {
- return (flags_ & STRING_ADD_CONVERT) != STRING_ADD_CONVERT;
- }
-
- const StringAddFlags flags_;
- const PretenureFlag pretenure_flag_;
-};
-
-
-class HStringCharCodeAt final : public HTemplateInstruction<3> {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HStringCharCodeAt,
- HValue*,
- HValue*);
-
- Representation RequiredInputRepresentation(int index) override {
- // The index is supposed to be Integer32.
- return index == 2
- ? Representation::Integer32()
- : Representation::Tagged();
- }
-
- HValue* context() const { return OperandAt(0); }
- HValue* string() const { return OperandAt(1); }
- HValue* index() const { return OperandAt(2); }
-
- DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- Range* InferRange(Zone* zone) override {
- return new(zone) Range(0, String::kMaxUtf16CodeUnit);
- }
-
- private:
- HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
- SetOperandAt(0, context);
- SetOperandAt(1, string);
- SetOperandAt(2, index);
- set_representation(Representation::Integer32());
- SetFlag(kUseGVN);
- SetDependsOnFlag(kMaps);
- SetDependsOnFlag(kStringChars);
- SetChangesFlag(kNewSpacePromotion);
- }
-
- // No side effects: runtime function assumes string + number inputs.
- bool IsDeletable() const override { return true; }
-};
-
-
-class HStringCharFromCode final : public HTemplateInstruction<2> {
- public:
- static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
- HValue* char_code);
-
- Representation RequiredInputRepresentation(int index) override {
- return index == 0
- ? Representation::Tagged()
- : Representation::Integer32();
- }
-
- HValue* context() const { return OperandAt(0); }
- HValue* value() const { return OperandAt(1); }
-
- bool DataEquals(HValue* other) override { return true; }
-
- DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
-
- private:
- HStringCharFromCode(HValue* context, HValue* char_code)
- : HTemplateInstruction<2>(HType::String()) {
- SetOperandAt(0, context);
- SetOperandAt(1, char_code);
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetChangesFlag(kNewSpacePromotion);
- }
-
- bool IsDeletable() const override {
- return !value()->ToNumberCanBeObserved();
- }
-};
-
-
-template <int V>
-class HMaterializedLiteral : public HTemplateInstruction<V> {
- public:
- HMaterializedLiteral<V>(int index, int depth, AllocationSiteMode mode)
- : literal_index_(index), depth_(depth), allocation_site_mode_(mode) {
- this->set_representation(Representation::Tagged());
- }
-
- HMaterializedLiteral<V>(int index, int depth)
- : literal_index_(index), depth_(depth),
- allocation_site_mode_(DONT_TRACK_ALLOCATION_SITE) {
- this->set_representation(Representation::Tagged());
- }
-
- int literal_index() const { return literal_index_; }
- int depth() const { return depth_; }
- AllocationSiteMode allocation_site_mode() const {
- return allocation_site_mode_;
- }
-
- private:
- bool IsDeletable() const final { return true; }
-
- int literal_index_;
- int depth_;
- AllocationSiteMode allocation_site_mode_;
-};
-
-
-class HRegExpLiteral final : public HMaterializedLiteral<1> {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HRegExpLiteral,
- Handle<FixedArray>,
- Handle<String>,
- Handle<String>,
- int);
-
- HValue* context() { return OperandAt(0); }
- Handle<FixedArray> literals() { return literals_; }
- Handle<String> pattern() { return pattern_; }
- Handle<String> flags() { return flags_; }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral)
-
- private:
- HRegExpLiteral(HValue* context,
- Handle<FixedArray> literals,
- Handle<String> pattern,
- Handle<String> flags,
- int literal_index)
- : HMaterializedLiteral<1>(literal_index, 0),
- literals_(literals),
- pattern_(pattern),
- flags_(flags) {
- SetOperandAt(0, context);
- SetAllSideEffects();
- set_type(HType::JSObject());
- }
-
- Handle<FixedArray> literals_;
- Handle<String> pattern_;
- Handle<String> flags_;
-};
-
-
-class HTypeof final : public HTemplateInstruction<2> {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HTypeof, HValue*);
-
- HValue* context() const { return OperandAt(0); }
- HValue* value() const { return OperandAt(1); }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Typeof)
-
- private:
- explicit HTypeof(HValue* context, HValue* value) {
- SetOperandAt(0, context);
- SetOperandAt(1, value);
- set_representation(Representation::Tagged());
- }
-
- bool IsDeletable() const override { return true; }
-};
-
-
-class HTrapAllocationMemento final : public HTemplateInstruction<1> {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HTrapAllocationMemento, HValue*);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- HValue* object() { return OperandAt(0); }
-
- DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento)
-
- private:
- explicit HTrapAllocationMemento(HValue* obj) {
- SetOperandAt(0, obj);
- }
-};
-
-
-class HMaybeGrowElements final : public HTemplateInstruction<5> {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P6(HMaybeGrowElements, HValue*,
- HValue*, HValue*, HValue*, bool,
- ElementsKind);
-
- Representation RequiredInputRepresentation(int index) override {
- if (index < 3) {
- return Representation::Tagged();
- }
- DCHECK(index == 3 || index == 4);
- return Representation::Integer32();
- }
-
- HValue* context() const { return OperandAt(0); }
- HValue* object() const { return OperandAt(1); }
- HValue* elements() const { return OperandAt(2); }
- HValue* key() const { return OperandAt(3); }
- HValue* current_capacity() const { return OperandAt(4); }
-
- bool is_js_array() const { return is_js_array_; }
- ElementsKind kind() const { return kind_; }
-
- DECLARE_CONCRETE_INSTRUCTION(MaybeGrowElements)
-
- protected:
- bool DataEquals(HValue* other) override { return true; }
-
- private:
- explicit HMaybeGrowElements(HValue* context, HValue* object, HValue* elements,
- HValue* key, HValue* current_capacity,
- bool is_js_array, ElementsKind kind) {
- is_js_array_ = is_js_array;
- kind_ = kind;
-
- SetOperandAt(0, context);
- SetOperandAt(1, object);
- SetOperandAt(2, elements);
- SetOperandAt(3, key);
- SetOperandAt(4, current_capacity);
-
- SetFlag(kUseGVN);
- SetChangesFlag(kElementsPointer);
- SetChangesFlag(kNewSpacePromotion);
- set_representation(Representation::Tagged());
- }
-
- bool is_js_array_;
- ElementsKind kind_;
-};
-
-
-class HToFastProperties final : public HUnaryOperation {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HToFastProperties, HValue*);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(ToFastProperties)
-
- private:
- explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
- set_representation(Representation::Tagged());
- SetChangesFlag(kNewSpacePromotion);
-
- // This instruction is not marked as kChangesMaps, but does
- // change the map of the input operand. Use it only when creating
- // object literals via a runtime call.
- DCHECK(value->IsCallRuntime());
-#ifdef DEBUG
- const Runtime::Function* function = HCallRuntime::cast(value)->function();
- DCHECK(function->function_id == Runtime::kCreateObjectLiteral);
-#endif
- }
-
- bool IsDeletable() const override { return true; }
-};
-
-
-class HDateField final : public HUnaryOperation {
- public:
- DECLARE_INSTRUCTION_FACTORY_P2(HDateField, HValue*, Smi*);
-
- Smi* index() const { return index_; }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(DateField)
-
- private:
- HDateField(HValue* date, Smi* index)
- : HUnaryOperation(date), index_(index) {
- set_representation(Representation::Tagged());
- }
-
- Smi* index_;
-};
-
-
-class HSeqStringGetChar final : public HTemplateInstruction<2> {
- public:
- static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
- String::Encoding encoding, HValue* string,
- HValue* index);
-
- Representation RequiredInputRepresentation(int index) override {
- return (index == 0) ? Representation::Tagged()
- : Representation::Integer32();
- }
-
- String::Encoding encoding() const { return encoding_; }
- HValue* string() const { return OperandAt(0); }
- HValue* index() const { return OperandAt(1); }
-
- DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar)
-
- protected:
- bool DataEquals(HValue* other) override {
- return encoding() == HSeqStringGetChar::cast(other)->encoding();
- }
-
- Range* InferRange(Zone* zone) override {
- if (encoding() == String::ONE_BYTE_ENCODING) {
- return new(zone) Range(0, String::kMaxOneByteCharCode);
- } else {
- DCHECK_EQ(String::TWO_BYTE_ENCODING, encoding());
- return new(zone) Range(0, String::kMaxUtf16CodeUnit);
- }
- }
-
- private:
- HSeqStringGetChar(String::Encoding encoding,
- HValue* string,
- HValue* index) : encoding_(encoding) {
- SetOperandAt(0, string);
- SetOperandAt(1, index);
- set_representation(Representation::Integer32());
- SetFlag(kUseGVN);
- SetDependsOnFlag(kStringChars);
- }
-
- bool IsDeletable() const override { return true; }
-
- String::Encoding encoding_;
-};
-
-
-class HSeqStringSetChar final : public HTemplateInstruction<4> {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(
- HSeqStringSetChar, String::Encoding,
- HValue*, HValue*, HValue*);
-
- String::Encoding encoding() { return encoding_; }
- HValue* context() { return OperandAt(0); }
- HValue* string() { return OperandAt(1); }
- HValue* index() { return OperandAt(2); }
- HValue* value() { return OperandAt(3); }
-
- Representation RequiredInputRepresentation(int index) override {
- return (index <= 1) ? Representation::Tagged()
- : Representation::Integer32();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar)
-
- private:
- HSeqStringSetChar(HValue* context,
- String::Encoding encoding,
- HValue* string,
- HValue* index,
- HValue* value) : encoding_(encoding) {
- SetOperandAt(0, context);
- SetOperandAt(1, string);
- SetOperandAt(2, index);
- SetOperandAt(3, value);
- set_representation(Representation::Tagged());
- SetChangesFlag(kStringChars);
- }
-
- String::Encoding encoding_;
-};
-
-
-class HCheckMapValue final : public HTemplateInstruction<2> {
- public:
- DECLARE_INSTRUCTION_FACTORY_P2(HCheckMapValue, HValue*, HValue*);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- HType CalculateInferredType() override {
- if (value()->type().IsHeapObject()) return value()->type();
- return HType::HeapObject();
- }
-
- HValue* value() const { return OperandAt(0); }
- HValue* map() const { return OperandAt(1); }
-
- HValue* Canonicalize() override;
-
- DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
-
- protected:
- int RedefinedOperandIndex() override { return 0; }
-
- bool DataEquals(HValue* other) override { return true; }
-
- private:
- HCheckMapValue(HValue* value, HValue* map)
- : HTemplateInstruction<2>(HType::HeapObject()) {
- SetOperandAt(0, value);
- SetOperandAt(1, map);
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetDependsOnFlag(kMaps);
- SetDependsOnFlag(kElementsKind);
- }
-};
-
-
-class HForInPrepareMap final : public HTemplateInstruction<2> {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HForInPrepareMap, HValue*);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- HValue* context() const { return OperandAt(0); }
- HValue* enumerable() const { return OperandAt(1); }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- HType CalculateInferredType() override { return HType::Tagged(); }
-
- DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
-
- private:
- HForInPrepareMap(HValue* context,
- HValue* object) {
- SetOperandAt(0, context);
- SetOperandAt(1, object);
- set_representation(Representation::Tagged());
- SetAllSideEffects();
- }
-};
-
-
-class HForInCacheArray final : public HTemplateInstruction<2> {
- public:
- DECLARE_INSTRUCTION_FACTORY_P3(HForInCacheArray, HValue*, HValue*, int);
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- HValue* enumerable() const { return OperandAt(0); }
- HValue* map() const { return OperandAt(1); }
- int idx() const { return idx_; }
-
- HForInCacheArray* index_cache() {
- return index_cache_;
- }
-
- void set_index_cache(HForInCacheArray* index_cache) {
- index_cache_ = index_cache;
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- HType CalculateInferredType() override { return HType::Tagged(); }
-
- DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
-
- private:
- HForInCacheArray(HValue* enumerable,
- HValue* keys,
- int idx) : idx_(idx) {
- SetOperandAt(0, enumerable);
- SetOperandAt(1, keys);
- set_representation(Representation::Tagged());
- }
-
- int idx_;
- HForInCacheArray* index_cache_;
-};
-
-
-class HLoadFieldByIndex final : public HTemplateInstruction<2> {
- public:
- DECLARE_INSTRUCTION_FACTORY_P2(HLoadFieldByIndex, HValue*, HValue*);
-
- HLoadFieldByIndex(HValue* object,
- HValue* index) {
- SetOperandAt(0, object);
- SetOperandAt(1, index);
- SetChangesFlag(kNewSpacePromotion);
- set_representation(Representation::Tagged());
- }
-
- Representation RequiredInputRepresentation(int index) override {
- if (index == 1) {
- return Representation::Smi();
- } else {
- return Representation::Tagged();
- }
- }
-
- HValue* object() const { return OperandAt(0); }
- HValue* index() const { return OperandAt(1); }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- HType CalculateInferredType() override { return HType::Tagged(); }
-
- DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
-
- private:
- bool IsDeletable() const override { return true; }
-};
-
-
-class HStoreFrameContext: public HUnaryOperation {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HStoreFrameContext, HValue*);
-
- HValue* context() { return OperandAt(0); }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(StoreFrameContext)
- private:
- explicit HStoreFrameContext(HValue* context)
- : HUnaryOperation(context) {
- set_representation(Representation::Tagged());
- SetChangesFlag(kContextSlots);
- }
-};
-
-
-class HAllocateBlockContext: public HTemplateInstruction<2> {
- public:
- DECLARE_INSTRUCTION_FACTORY_P3(HAllocateBlockContext, HValue*,
- HValue*, Handle<ScopeInfo>);
- HValue* context() const { return OperandAt(0); }
- HValue* function() const { return OperandAt(1); }
- Handle<ScopeInfo> scope_info() const { return scope_info_; }
-
- Representation RequiredInputRepresentation(int index) override {
- return Representation::Tagged();
- }
-
- std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
-
- DECLARE_CONCRETE_INSTRUCTION(AllocateBlockContext)
-
- private:
- HAllocateBlockContext(HValue* context,
- HValue* function,
- Handle<ScopeInfo> scope_info)
- : scope_info_(scope_info) {
- SetOperandAt(0, context);
- SetOperandAt(1, function);
- set_representation(Representation::Tagged());
- }
-
- Handle<ScopeInfo> scope_info_;
-};
-
-
-
-#undef DECLARE_INSTRUCTION
-#undef DECLARE_CONCRETE_INSTRUCTION
-
-} // namespace internal
-} // namespace v8
-
-#endif // V8_HYDROGEN_INSTRUCTIONS_H_
« no previous file with comments | « src/hydrogen-infer-types.cc ('k') | src/hydrogen-instructions.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698