summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/v8/src/hydrogen-instructions.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/v8/src/hydrogen-instructions.h')
-rw-r--r--src/3rdparty/v8/src/hydrogen-instructions.h6186
1 files changed, 0 insertions, 6186 deletions
diff --git a/src/3rdparty/v8/src/hydrogen-instructions.h b/src/3rdparty/v8/src/hydrogen-instructions.h
deleted file mode 100644
index 7c2135d..0000000
--- a/src/3rdparty/v8/src/hydrogen-instructions.h
+++ /dev/null
@@ -1,6186 +0,0 @@
-// Copyright 2012 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef V8_HYDROGEN_INSTRUCTIONS_H_
-#define V8_HYDROGEN_INSTRUCTIONS_H_
-
-#include "v8.h"
-
-#include "allocation.h"
-#include "code-stubs.h"
-#include "data-flow.h"
-#include "small-pointer-list.h"
-#include "string-stream.h"
-#include "v8conversions.h"
-#include "v8utils.h"
-#include "zone.h"
-
-namespace v8 {
-namespace internal {
-
-// Forward declarations.
-class HBasicBlock;
-class HEnvironment;
-class HInferRepresentation;
-class HInstruction;
-class HLoopInformation;
-class HValue;
-class LInstruction;
-class LChunkBuilder;
-
-
-#define HYDROGEN_ABSTRACT_INSTRUCTION_LIST(V) \
- V(BinaryOperation) \
- V(BitwiseBinaryOperation) \
- V(ControlInstruction) \
- V(Instruction) \
-
-
-#define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
- V(AbnormalExit) \
- V(AccessArgumentsAt) \
- V(Add) \
- V(Allocate) \
- V(AllocateObject) \
- V(ApplyArguments) \
- V(ArgumentsElements) \
- V(ArgumentsLength) \
- V(ArgumentsObject) \
- V(ArrayLiteral) \
- V(Bitwise) \
- V(BitNot) \
- V(BlockEntry) \
- V(BoundsCheck) \
- V(Branch) \
- V(CallConstantFunction) \
- V(CallFunction) \
- V(CallGlobal) \
- V(CallKeyed) \
- V(CallKnownGlobal) \
- V(CallNamed) \
- V(CallNew) \
- V(CallNewArray) \
- V(CallRuntime) \
- V(CallStub) \
- V(Change) \
- V(CheckFunction) \
- V(CheckInstanceType) \
- V(CheckMaps) \
- V(CheckNonSmi) \
- V(CheckPrototypeMaps) \
- V(CheckSmi) \
- V(CheckSmiOrInt32) \
- V(ClampToUint8) \
- V(ClassOfTestAndBranch) \
- V(CompareIDAndBranch) \
- V(CompareGeneric) \
- V(CompareObjectEqAndBranch) \
- V(CompareMap) \
- V(CompareConstantEqAndBranch) \
- V(Constant) \
- V(Context) \
- V(DeclareGlobals) \
- V(DeleteProperty) \
- V(Deoptimize) \
- V(Div) \
- V(DummyUse) \
- V(ElementsKind) \
- V(EnterInlined) \
- V(FastLiteral) \
- V(FixedArrayBaseLength) \
- V(ForceRepresentation) \
- V(FunctionLiteral) \
- V(GetCachedArrayIndex) \
- V(GlobalObject) \
- V(GlobalReceiver) \
- V(Goto) \
- V(HasCachedArrayIndexAndBranch) \
- V(HasInstanceTypeAndBranch) \
- V(InductionVariableAnnotation) \
- V(In) \
- V(InstanceOf) \
- V(InstanceOfKnownGlobal) \
- V(InstanceSize) \
- V(InvokeFunction) \
- V(IsConstructCallAndBranch) \
- V(IsNilAndBranch) \
- V(IsObjectAndBranch) \
- V(IsStringAndBranch) \
- V(IsSmiAndBranch) \
- V(IsUndetectableAndBranch) \
- V(JSArrayLength) \
- V(LeaveInlined) \
- V(LoadContextSlot) \
- V(LoadElements) \
- V(LoadExternalArrayPointer) \
- V(LoadFunctionPrototype) \
- V(LoadGlobalCell) \
- V(LoadGlobalGeneric) \
- V(LoadKeyed) \
- V(LoadKeyedGeneric) \
- V(LoadNamedField) \
- V(LoadNamedFieldPolymorphic) \
- V(LoadNamedGeneric) \
- V(MapEnumLength) \
- V(MathFloorOfDiv) \
- V(MathMinMax) \
- V(Mod) \
- V(Mul) \
- V(NumericConstraint) \
- V(ObjectLiteral) \
- V(OsrEntry) \
- V(OuterContext) \
- V(Parameter) \
- V(Power) \
- V(PushArgument) \
- V(Random) \
- V(RegExpLiteral) \
- V(Return) \
- V(Ror) \
- V(Sar) \
- V(SeqStringSetChar) \
- V(Shl) \
- V(Shr) \
- V(Simulate) \
- V(SoftDeoptimize) \
- V(StackCheck) \
- V(StoreContextSlot) \
- V(StoreGlobalCell) \
- V(StoreGlobalGeneric) \
- V(StoreKeyed) \
- V(StoreKeyedGeneric) \
- V(StoreNamedField) \
- V(StoreNamedGeneric) \
- V(StringAdd) \
- V(StringCharCodeAt) \
- V(StringCharFromCode) \
- V(StringCompareAndBranch) \
- V(StringLength) \
- V(Sub) \
- V(ThisFunction) \
- V(Throw) \
- V(ToFastProperties) \
- V(TransitionElementsKind) \
- V(TrapAllocationMemento) \
- V(Typeof) \
- V(TypeofIsAndBranch) \
- V(UnaryMathOperation) \
- V(UnknownOSRValue) \
- V(UseConst) \
- V(ValueOf) \
- V(ForInPrepareMap) \
- V(ForInCacheArray) \
- V(CheckMapValue) \
- V(LoadFieldByIndex) \
- V(DateField) \
- V(WrapReceiver)
-
-#define GVN_TRACKED_FLAG_LIST(V) \
- V(Maps) \
- V(NewSpacePromotion)
-
-#define GVN_UNTRACKED_FLAG_LIST(V) \
- V(Calls) \
- V(InobjectFields) \
- V(BackingStoreFields) \
- V(ElementsKind) \
- V(ElementsPointer) \
- V(ArrayElements) \
- V(DoubleArrayElements) \
- V(SpecializedArrayElements) \
- V(GlobalVars) \
- V(ArrayLengths) \
- V(ContextSlots) \
- V(OsrEntries)
-
-#define DECLARE_ABSTRACT_INSTRUCTION(type) \
- virtual bool Is##type() const { return true; } \
- static H##type* cast(HValue* value) { \
- ASSERT(value->Is##type()); \
- return reinterpret_cast<H##type*>(value); \
- }
-
-
-#define DECLARE_CONCRETE_INSTRUCTION(type) \
- virtual LInstruction* CompileToLithium(LChunkBuilder* builder); \
- static H##type* cast(HValue* value) { \
- ASSERT(value->Is##type()); \
- return reinterpret_cast<H##type*>(value); \
- } \
- virtual Opcode opcode() const { return HValue::k##type; }
-
-
-#ifdef DEBUG
-#define ASSERT_ALLOCATION_DISABLED \
- ASSERT(isolate()->optimizing_compiler_thread()->IsOptimizerThread() || \
- !isolate()->heap()->IsAllocationAllowed())
-#else
-#define ASSERT_ALLOCATION_DISABLED do {} while (0)
-#endif
-
-class Range: 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 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 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(Range* other);
- bool SubAndCheckOverflow(Range* other);
- bool MulAndCheckOverflow(Range* other);
-
- private:
- int32_t lower_;
- int32_t upper_;
- Range* next_;
- bool can_be_minus_zero_;
-};
-
-
-class Representation {
- public:
- enum Kind {
- kNone,
- kInteger32,
- kDouble,
- kTagged,
- kExternal,
- kNumRepresentations
- };
-
- Representation() : kind_(kNone) { }
-
- static Representation None() { return Representation(kNone); }
- static Representation Tagged() { return Representation(kTagged); }
- static Representation Integer32() { return Representation(kInteger32); }
- static Representation Double() { return Representation(kDouble); }
- static Representation External() { return Representation(kExternal); }
-
- static Representation FromKind(Kind kind) { return Representation(kind); }
-
- bool Equals(const Representation& other) {
- return kind_ == other.kind_;
- }
-
- bool is_more_general_than(const Representation& other) {
- ASSERT(kind_ != kExternal);
- ASSERT(other.kind_ != kExternal);
- return kind_ > other.kind_;
- }
-
- Kind kind() const { return static_cast<Kind>(kind_); }
- bool IsNone() const { return kind_ == kNone; }
- bool IsTagged() const { return kind_ == kTagged; }
- bool IsInteger32() const { return kind_ == kInteger32; }
- bool IsDouble() const { return kind_ == kDouble; }
- bool IsExternal() const { return kind_ == kExternal; }
- bool IsSpecialization() const {
- return kind_ == kInteger32 || kind_ == kDouble;
- }
- const char* Mnemonic() const;
-
- private:
- explicit Representation(Kind k) : kind_(k) { }
-
- // Make sure kind fits in int8.
- STATIC_ASSERT(kNumRepresentations <= (1 << kBitsPerByte));
-
- int8_t kind_;
-};
-
-
-class HType {
- public:
- HType() : type_(kUninitialized) { }
-
- static HType Tagged() { return HType(kTagged); }
- static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
- static HType TaggedNumber() { return HType(kTaggedNumber); }
- static HType Smi() { return HType(kSmi); }
- static HType HeapNumber() { return HType(kHeapNumber); }
- static HType String() { return HType(kString); }
- static HType Boolean() { return HType(kBoolean); }
- static HType NonPrimitive() { return HType(kNonPrimitive); }
- static HType JSArray() { return HType(kJSArray); }
- static HType JSObject() { return HType(kJSObject); }
- static HType Uninitialized() { return HType(kUninitialized); }
-
- // Return the weakest (least precise) common type.
- HType Combine(HType other) {
- return HType(static_cast<Type>(type_ & other.type_));
- }
-
- bool Equals(const HType& other) {
- return type_ == other.type_;
- }
-
- bool IsSubtypeOf(const HType& other) {
- return Combine(other).Equals(other);
- }
-
- bool IsTagged() {
- ASSERT(type_ != kUninitialized);
- return ((type_ & kTagged) == kTagged);
- }
-
- bool IsTaggedPrimitive() {
- ASSERT(type_ != kUninitialized);
- return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
- }
-
- bool IsTaggedNumber() {
- ASSERT(type_ != kUninitialized);
- return ((type_ & kTaggedNumber) == kTaggedNumber);
- }
-
- bool IsSmi() {
- ASSERT(type_ != kUninitialized);
- return ((type_ & kSmi) == kSmi);
- }
-
- bool IsHeapNumber() {
- ASSERT(type_ != kUninitialized);
- return ((type_ & kHeapNumber) == kHeapNumber);
- }
-
- bool IsString() {
- ASSERT(type_ != kUninitialized);
- return ((type_ & kString) == kString);
- }
-
- bool IsBoolean() {
- ASSERT(type_ != kUninitialized);
- return ((type_ & kBoolean) == kBoolean);
- }
-
- bool IsNonPrimitive() {
- ASSERT(type_ != kUninitialized);
- return ((type_ & kNonPrimitive) == kNonPrimitive);
- }
-
- bool IsJSArray() {
- ASSERT(type_ != kUninitialized);
- return ((type_ & kJSArray) == kJSArray);
- }
-
- bool IsJSObject() {
- ASSERT(type_ != kUninitialized);
- return ((type_ & kJSObject) == kJSObject);
- }
-
- bool IsUninitialized() {
- return type_ == kUninitialized;
- }
-
- bool IsHeapObject() {
- ASSERT(type_ != kUninitialized);
- return IsHeapNumber() || IsString() || IsNonPrimitive();
- }
-
- static HType TypeFromValue(Isolate* isolate, Handle<Object> value);
-
- const char* ToString();
-
- private:
- enum Type {
- kTagged = 0x1, // 0000 0000 0000 0001
- kTaggedPrimitive = 0x5, // 0000 0000 0000 0101
- kTaggedNumber = 0xd, // 0000 0000 0000 1101
- kSmi = 0x1d, // 0000 0000 0001 1101
- kHeapNumber = 0x2d, // 0000 0000 0010 1101
- kString = 0x45, // 0000 0000 0100 0101
- kBoolean = 0x85, // 0000 0000 1000 0101
- kNonPrimitive = 0x101, // 0000 0001 0000 0001
- kJSObject = 0x301, // 0000 0011 0000 0001
- kJSArray = 0x701, // 0000 0111 0000 0001
- kUninitialized = 0x1fff // 0001 1111 1111 1111
- };
-
- // Make sure type fits in int16.
- STATIC_ASSERT(kUninitialized < (1 << (2 * kBitsPerByte)));
-
- explicit HType(Type t) : type_(t) { }
-
- int16_t type_;
-};
-
-
-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 BASE_EMBEDDED {
- public:
- bool Done() { return current_ == NULL; }
- void Advance();
-
- HValue* value() {
- ASSERT(!Done());
- return value_;
- }
-
- int index() {
- ASSERT(!Done());
- return index_;
- }
-
- private:
- explicit HUseIterator(HUseListNode* head);
-
- HUseListNode* current_;
- HUseListNode* next_;
- HValue* value_;
- int index_;
-
- friend class HValue;
-};
-
-
-// There must be one corresponding kDepends flag for every kChanges flag and
-// the order of the kChanges flags must be exactly the same as of the kDepends
-// flags. All tracked flags should appear before untracked ones.
-enum GVNFlag {
- // Declare global value numbering flags.
-#define DECLARE_FLAG(type) kChanges##type, kDependsOn##type,
- GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
- GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
-#undef DECLARE_FLAG
- kAfterLastFlag,
- kLastFlag = kAfterLastFlag - 1,
-#define COUNT_FLAG(type) + 1
- kNumberOfTrackedSideEffects = 0 GVN_TRACKED_FLAG_LIST(COUNT_FLAG)
-#undef COUNT_FLAG
-};
-
-
-class NumericRelation {
- public:
- enum Kind { NONE, EQ, GT, GE, LT, LE, NE };
- static const char* MnemonicFromKind(Kind kind) {
- switch (kind) {
- case NONE: return "NONE";
- case EQ: return "EQ";
- case GT: return "GT";
- case GE: return "GE";
- case LT: return "LT";
- case LE: return "LE";
- case NE: return "NE";
- }
- UNREACHABLE();
- return NULL;
- }
- const char* Mnemonic() const { return MnemonicFromKind(kind_); }
-
- static NumericRelation None() { return NumericRelation(NONE); }
- static NumericRelation Eq() { return NumericRelation(EQ); }
- static NumericRelation Gt() { return NumericRelation(GT); }
- static NumericRelation Ge() { return NumericRelation(GE); }
- static NumericRelation Lt() { return NumericRelation(LT); }
- static NumericRelation Le() { return NumericRelation(LE); }
- static NumericRelation Ne() { return NumericRelation(NE); }
-
- bool IsNone() { return kind_ == NONE; }
-
- static NumericRelation FromToken(Token::Value token) {
- switch (token) {
- case Token::EQ: return Eq();
- case Token::EQ_STRICT: return Eq();
- case Token::LT: return Lt();
- case Token::GT: return Gt();
- case Token::LTE: return Le();
- case Token::GTE: return Ge();
- case Token::NE: return Ne();
- case Token::NE_STRICT: return Ne();
- default: return None();
- }
- }
-
- // The semantics of "Reversed" is that if "x rel y" is true then also
- // "y rel.Reversed() x" is true, and that rel.Reversed().Reversed() == rel.
- NumericRelation Reversed() {
- switch (kind_) {
- case NONE: return None();
- case EQ: return Eq();
- case GT: return Lt();
- case GE: return Le();
- case LT: return Gt();
- case LE: return Ge();
- case NE: return Ne();
- }
- UNREACHABLE();
- return None();
- }
-
- // The semantics of "Negated" is that if "x rel y" is true then also
- // "!(x rel.Negated() y)" is true.
- NumericRelation Negated() {
- switch (kind_) {
- case NONE: return None();
- case EQ: return Ne();
- case GT: return Le();
- case GE: return Lt();
- case LT: return Ge();
- case LE: return Gt();
- case NE: return Eq();
- }
- UNREACHABLE();
- return None();
- }
-
- // The semantics of "Implies" is that if "x rel y" is true
- // then also "x other_relation y" is true.
- bool Implies(NumericRelation other_relation) {
- switch (kind_) {
- case NONE: return false;
- case EQ: return (other_relation.kind_ == EQ)
- || (other_relation.kind_ == GE)
- || (other_relation.kind_ == LE);
- case GT: return (other_relation.kind_ == GT)
- || (other_relation.kind_ == GE)
- || (other_relation.kind_ == NE);
- case LT: return (other_relation.kind_ == LT)
- || (other_relation.kind_ == LE)
- || (other_relation.kind_ == NE);
- case GE: return (other_relation.kind_ == GE);
- case LE: return (other_relation.kind_ == LE);
- case NE: return (other_relation.kind_ == NE);
- }
- UNREACHABLE();
- return false;
- }
-
- // The semantics of "IsExtendable" is that if
- // "rel.IsExtendable(direction)" is true then
- // "x rel y" implies "(x + direction) rel y" .
- bool IsExtendable(int direction) {
- switch (kind_) {
- case NONE: return false;
- case EQ: return false;
- case GT: return (direction >= 0);
- case GE: return (direction >= 0);
- case LT: return (direction <= 0);
- case LE: return (direction <= 0);
- case NE: return false;
- }
- UNREACHABLE();
- return false;
- }
-
- private:
- explicit NumericRelation(Kind kind) : kind_(kind) {}
-
- Kind kind_;
-};
-
-
-typedef EnumSet<GVNFlag> GVNFlagSet;
-
-
-class HValue: public ZoneObject {
- public:
- static const int kNoNumber = -1;
-
- enum Flag {
- kFlexibleRepresentation,
- // 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 SetSideEffectDominator() and should
- // indicate which side effects to track by setting GVN flags.
- kTrackSideEffectDominators,
- kCanOverflow,
- kBailoutOnMinusZero,
- kCanBeDivByZero,
- kDeoptimizeOnUndefined,
- kIsArguments,
- kTruncatingToInt32,
- 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_UNSIGNED_INT_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,
- // If a phi is involved in the evaluation of a numeric constraint the
- // recursion can cause an endless cycle: we use this flag to exit the loop.
- kNumericConstraintEvaluationInProgress,
- // This flag is set to true after the SetupInformativeDefinitions() pass
- // has processed this instruction.
- kIDefsProcessingDone,
- kLastFlag = kIDefsProcessingDone
- };
-
- STATIC_ASSERT(kLastFlag < kBitsPerInt);
-
- static const int kChangesToDependsFlagsLeftShift = 1;
-
- static GVNFlag ChangesFlagFromInt(int x) {
- return static_cast<GVNFlag>(x * 2);
- }
- static GVNFlag DependsOnFlagFromInt(int x) {
- return static_cast<GVNFlag>(x * 2 + 1);
- }
- static GVNFlagSet ConvertChangesToDependsFlags(GVNFlagSet flags) {
- return GVNFlagSet(flags.ToIntegral() << kChangesToDependsFlagsLeftShift);
- }
-
- 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
-
- HValue() : block_(NULL),
- id_(kNoNumber),
- type_(HType::Tagged()),
- use_list_(NULL),
- range_(NULL),
- flags_(0) {}
- virtual ~HValue() {}
-
- HBasicBlock* block() const { return block_; }
- void SetBlock(HBasicBlock* block);
- int LoopWeight() const;
-
- // 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) {
- ASSERT(CheckFlag(kFlexibleRepresentation));
- 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 bool IsConvertibleToInteger() const { return true; }
-
- HType type() const { return type_; }
- void set_type(HType new_type) {
- ASSERT(new_type.IsSubtypeOf(type_));
- type_ = new_type;
- }
-
- // An operation needs to override this function iff:
- // 1) it can produce an int32 output.
- // 2) the true value of its output can potentially be minus zero.
- // The implementation must set a flag so that it bails out in the case where
- // it would otherwise output what should be a minus zero as an int32 zero.
- // If the operation also exists in a form that takes int32 and outputs int32
- // then the operation should return its input value so that we can propagate
- // back. There are three operations that need to propagate back to more than
- // one input. They are phi and binary div and mul. They always return NULL
- // and expect the caller to take care of things.
- virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) {
- visited->Add(id());
- return NULL;
- }
-
- // 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() {
- return IsInformativeDefinition() ? OperandAt(RedefinedOperandIndex())
- : NULL;
- }
-
- // 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 iDef of this value).
- HValue* ActualValue() {
- return IsInformativeDefinition() ? RedefinedOperand()->ActualValue()
- : this;
- }
-
- virtual void AddInformativeDefinitions() {}
-
- void UpdateRedefinedUsesWhileSettingUpInformativeDefinitions() {
- UpdateRedefinedUsesInner<TestDominanceUsingProcessedFlag>();
- }
- void UpdateRedefinedUses() {
- UpdateRedefinedUsesInner<Dominates>();
- }
-
- bool IsInteger32Constant();
- int32_t GetInteger32Constant();
-
- bool IsDefinedAfter(HBasicBlock* other) const;
-
- // Operands.
- virtual int OperandCount() = 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 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; }
-
- // Returns true if the flag specified is set for all uses, false otherwise.
- bool CheckUsesForFlag(Flag f);
-
- GVNFlagSet gvn_flags() const { return gvn_flags_; }
- void SetGVNFlag(GVNFlag f) { gvn_flags_.Add(f); }
- void ClearGVNFlag(GVNFlag f) { gvn_flags_.Remove(f); }
- bool CheckGVNFlag(GVNFlag f) const { return gvn_flags_.Contains(f); }
- void SetAllSideEffects() { gvn_flags_.Add(AllSideEffectsFlagSet()); }
- void ClearAllSideEffects() {
- gvn_flags_.Remove(AllSideEffectsFlagSet());
- }
- bool HasSideEffects() const {
- return gvn_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
- }
- bool HasObservableSideEffects() const {
- return gvn_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
- }
-
- GVNFlagSet DependsOnFlags() const {
- GVNFlagSet result = gvn_flags_;
- result.Intersect(AllDependsOnFlagSet());
- return result;
- }
-
- GVNFlagSet SideEffectFlags() const {
- GVNFlagSet result = gvn_flags_;
- result.Intersect(AllSideEffectsFlagSet());
- return result;
- }
-
- GVNFlagSet ChangesFlags() const {
- GVNFlagSet result = gvn_flags_;
- result.Intersect(AllChangesFlagSet());
- return result;
- }
-
- GVNFlagSet ObservableChangesFlags() const {
- GVNFlagSet result = gvn_flags_;
- result.Intersect(AllChangesFlagSet());
- result.Intersect(AllObservableSideEffectsFlagSet());
- return result;
- }
-
- Range* range() const { return range_; }
- bool HasRange() const { return range_ != NULL; }
- void AddNewRange(Range* r, Zone* zone);
- void RemoveLastAddedRange();
- void ComputeInitialRange(Zone* zone);
-
- // Representation helpers.
- virtual Representation observed_input_representation(int index) {
- return Representation::None();
- }
- virtual Representation RequiredInputRepresentation(int index) = 0;
- virtual void InferRepresentation(HInferRepresentation* 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();
-
- // Printing support.
- virtual void PrintTo(StringStream* stream) = 0;
- void PrintNameTo(StringStream* stream);
- void PrintTypeTo(StringStream* stream);
- void PrintRangeTo(StringStream* stream);
- void PrintChangesTo(StringStream* stream);
-
- 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.
- virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) {
- UNREACHABLE();
- }
-
- bool IsDead() const {
- return HasNoUses() && !HasObservableSideEffects() && IsDeletable();
- }
-
-#ifdef DEBUG
- virtual void Verify() = 0;
-#endif
-
- // This method is recursive but it is guaranteed to terminate because
- // RedefinedOperand() always dominates "this".
- bool IsRelationTrue(NumericRelation relation, HValue* other) {
- if (this == other) {
- return NumericRelation::Eq().Implies(relation);
- }
-
- bool result = IsRelationTrueInternal(relation, other) ||
- other->IsRelationTrueInternal(relation.Reversed(), this);
- if (!result) {
- HValue* redefined = RedefinedOperand();
- if (redefined != NULL) {
- result = redefined->IsRelationTrue(relation, other);
- }
- }
- return result;
- }
-
- 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;
- }
-
- virtual Representation RepresentationFromInputs() {
- return representation();
- }
- Representation RepresentationFromUses();
- virtual void UpdateRepresentation(Representation new_rep,
- HInferRepresentation* h_infer,
- const char* reason);
- void AddDependantsToWorklist(HInferRepresentation* 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() {
- ASSERT(block_ != NULL);
- block_ = NULL;
- }
-
- void set_representation(Representation r) {
- ASSERT(representation_.IsNone() && !r.IsNone());
- representation_ = r;
- }
-
- // Signature of a function testing if a HValue properly dominates another.
- typedef bool (*DominanceTest)(HValue*, HValue*);
-
- // Simple implementation of DominanceTest implemented walking the chain
- // of Hinstructions (used in UpdateRedefinedUsesInner).
- static bool Dominates(HValue* dominator, HValue* dominated);
-
- // A fast implementation of DominanceTest that works only for the
- // "current" instruction in the SetupInformativeDefinitions() phase.
- // During that phase we use a flag to mark processed instructions, and by
- // checking the flag we can quickly test if an instruction comes before or
- // after the "current" one.
- static bool TestDominanceUsingProcessedFlag(HValue* dominator,
- HValue* dominated);
-
- // If we are redefining an operand, update all its dominated uses (the
- // function that checks if a use is dominated is the template argument).
- template<DominanceTest TestDominance>
- void UpdateRedefinedUsesInner() {
- HValue* input = RedefinedOperand();
- if (input != NULL) {
- for (HUseIterator uses = input->uses(); !uses.Done(); uses.Advance()) {
- HValue* use = uses.value();
- if (TestDominance(this, use)) {
- use->SetOperandAt(uses.index(), this);
- }
- }
- }
- }
-
- // Informative definitions can override this method to state any numeric
- // relation they provide on the redefined value.
- virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* other) {
- return false;
- }
-
- static GVNFlagSet AllDependsOnFlagSet() {
- GVNFlagSet result;
- // Create changes mask.
-#define ADD_FLAG(type) result.Add(kDependsOn##type);
- GVN_TRACKED_FLAG_LIST(ADD_FLAG)
- GVN_UNTRACKED_FLAG_LIST(ADD_FLAG)
-#undef ADD_FLAG
- return result;
- }
-
- static GVNFlagSet AllChangesFlagSet() {
- GVNFlagSet result;
- // Create changes mask.
-#define ADD_FLAG(type) result.Add(kChanges##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 = AllChangesFlagSet();
- result.Remove(kChangesOsrEntries);
- return result;
- }
-
- // 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 = AllChangesFlagSet();
- result.Remove(kChangesNewSpacePromotion);
- result.Remove(kChangesElementsKind);
- result.Remove(kChangesElementsPointer);
- result.Remove(kChangesMaps);
- 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_;
- int flags_;
- GVNFlagSet gvn_flags_;
-
- private:
- virtual bool IsDeletable() const { return false; }
-
- DISALLOW_COPY_AND_ASSIGN(HValue);
-};
-
-
-class HInstruction: public HValue {
- public:
- HInstruction* next() const { return next_; }
- HInstruction* previous() const { return previous_; }
-
- virtual void PrintTo(StringStream* stream);
- virtual void PrintDataTo(StringStream* stream) { }
-
- bool IsLinked() const { return block() != NULL; }
- void Unlink();
- void InsertBefore(HInstruction* next);
- void InsertAfter(HInstruction* previous);
-
- // The position is a write-once variable.
- int position() const { return position_; }
- bool has_position() const { return position_ != RelocInfo::kNoPosition; }
- void set_position(int position) {
- ASSERT(!has_position());
- ASSERT(position != RelocInfo::kNoPosition);
- position_ = position;
- }
-
- bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); }
-
- virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
-
-#ifdef DEBUG
- virtual void Verify();
-#endif
-
- virtual bool IsCall() { return false; }
-
- DECLARE_ABSTRACT_INSTRUCTION(Instruction)
-
- protected:
- HInstruction()
- : next_(NULL),
- previous_(NULL),
- position_(RelocInfo::kNoPosition) {
- SetGVNFlag(kDependsOnOsrEntries);
- }
-
- virtual void DeleteFromGraph() { Unlink(); }
-
- private:
- void InitializeAsFirst(HBasicBlock* block) {
- ASSERT(!IsLinked());
- SetBlock(block);
- }
-
- void PrintMnemonicTo(StringStream* stream);
-
- HInstruction* next_;
- HInstruction* previous_;
- int position_;
-
- friend class HBasicBlock;
-};
-
-
-template<int V>
-class HTemplateInstruction : public HInstruction {
- public:
- int OperandCount() { return V; }
- HValue* OperandAt(int i) const { return inputs_[i]; }
-
- protected:
- void InternalSetOperandAt(int i, HValue* value) { inputs_[i] = value; }
-
- private:
- EmbeddedContainer<HValue*, V> inputs_;
-};
-
-
-class HControlInstruction: public HInstruction {
- public:
- virtual HBasicBlock* SuccessorAt(int i) = 0;
- virtual int SuccessorCount() = 0;
- virtual void SetSuccessorAt(int i, HBasicBlock* block) = 0;
-
- virtual void PrintDataTo(StringStream* stream);
-
- HBasicBlock* FirstSuccessor() {
- return SuccessorCount() > 0 ? SuccessorAt(0) : NULL;
- }
- HBasicBlock* SecondSuccessor() {
- return SuccessorCount() > 1 ? SuccessorAt(1) : NULL;
- }
-
- DECLARE_ABSTRACT_INSTRUCTION(ControlInstruction)
-};
-
-
-class HSuccessorIterator BASE_EMBEDDED {
- public:
- explicit HSuccessorIterator(HControlInstruction* instr)
- : instr_(instr), current_(0) { }
-
- bool Done() { return current_ >= instr_->SuccessorCount(); }
- HBasicBlock* Current() { return instr_->SuccessorAt(current_); }
- void Advance() { current_++; }
-
- private:
- HControlInstruction* instr_;
- int current_;
-};
-
-
-template<int S, int V>
-class HTemplateControlInstruction: public HControlInstruction {
- public:
- int SuccessorCount() { return S; }
- HBasicBlock* SuccessorAt(int i) { return successors_[i]; }
- void SetSuccessorAt(int i, HBasicBlock* block) { successors_[i] = block; }
-
- int OperandCount() { return V; }
- HValue* OperandAt(int i) const { return inputs_[i]; }
-
-
- protected:
- void InternalSetOperandAt(int i, HValue* value) { inputs_[i] = value; }
-
- private:
- EmbeddedContainer<HBasicBlock*, S> successors_;
- EmbeddedContainer<HValue*, V> inputs_;
-};
-
-
-class HBlockEntry: public HTemplateInstruction<0> {
- public:
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(BlockEntry)
-};
-
-
-class HDummyUse: public HTemplateInstruction<1> {
- public:
- explicit HDummyUse(HValue* value) {
- 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());
- set_type(HType::Smi());
- }
-
- HValue* value() { return OperandAt(0); }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- DECLARE_CONCRETE_INSTRUCTION(DummyUse);
-};
-
-
-class HNumericConstraint : public HTemplateInstruction<2> {
- public:
- static HNumericConstraint* AddToGraph(HValue* constrained_value,
- NumericRelation relation,
- HValue* related_value,
- HInstruction* insertion_point = NULL);
-
- HValue* constrained_value() { return OperandAt(0); }
- HValue* related_value() { return OperandAt(1); }
- NumericRelation relation() { return relation_; }
-
- virtual int RedefinedOperandIndex() { return 0; }
- virtual bool IsPurelyInformativeDefinition() { return true; }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return representation();
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual bool IsRelationTrueInternal(NumericRelation other_relation,
- HValue* other_related_value) {
- if (related_value() == other_related_value) {
- return relation().Implies(other_relation);
- } else {
- return false;
- }
- }
-
- DECLARE_CONCRETE_INSTRUCTION(NumericConstraint)
-
- private:
- HNumericConstraint(HValue* constrained_value,
- NumericRelation relation,
- HValue* related_value)
- : relation_(relation) {
- SetOperandAt(0, constrained_value);
- SetOperandAt(1, related_value);
- set_representation(constrained_value->representation());
- }
-
- NumericRelation relation_;
-};
-
-
-// We insert soft-deoptimize when we hit code with unknown typefeedback,
-// so that we get a chance of re-optimizing with useful typefeedback.
-// HSoftDeoptimize does not end a basic block as opposed to HDeoptimize.
-class HSoftDeoptimize: public HTemplateInstruction<0> {
- public:
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(SoftDeoptimize)
-};
-
-
-class HDeoptimize: public HControlInstruction {
- public:
- HDeoptimize(int environment_length, Zone* zone)
- : values_(environment_length, zone) { }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- virtual int OperandCount() { return values_.length(); }
- virtual HValue* OperandAt(int index) const { return values_[index]; }
- virtual void PrintDataTo(StringStream* stream);
-
- virtual int SuccessorCount() { return 0; }
- virtual HBasicBlock* SuccessorAt(int i) {
- UNREACHABLE();
- return NULL;
- }
- virtual void SetSuccessorAt(int i, HBasicBlock* block) {
- UNREACHABLE();
- }
-
- void AddEnvironmentValue(HValue* value, Zone* zone) {
- values_.Add(NULL, zone);
- SetOperandAt(values_.length() - 1, value);
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
-
- enum UseEnvironment {
- kNoUses,
- kUseAll
- };
-
- protected:
- virtual void InternalSetOperandAt(int index, HValue* value) {
- values_[index] = value;
- }
-
- private:
- ZoneList<HValue*> values_;
-};
-
-
-class HGoto: public HTemplateControlInstruction<1, 0> {
- public:
- explicit HGoto(HBasicBlock* target) {
- SetSuccessorAt(0, target);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- DECLARE_CONCRETE_INSTRUCTION(Goto)
-};
-
-
-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);
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- HValue* value() { return OperandAt(0); }
-};
-
-
-class HBranch: public HUnaryControlInstruction {
- public:
- HBranch(HValue* value,
- HBasicBlock* true_target,
- HBasicBlock* false_target,
- ToBooleanStub::Types expected_input_types = ToBooleanStub::no_types())
- : HUnaryControlInstruction(value, true_target, false_target),
- expected_input_types_(expected_input_types) {
- ASSERT(true_target != NULL && false_target != NULL);
- }
- explicit HBranch(HValue* value)
- : HUnaryControlInstruction(value, NULL, NULL) { }
-
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
- virtual Representation observed_input_representation(int index);
-
- ToBooleanStub::Types expected_input_types() const {
- return expected_input_types_;
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Branch)
-
- private:
- ToBooleanStub::Types expected_input_types_;
-};
-
-
-class HCompareMap: public HUnaryControlInstruction {
- public:
- HCompareMap(HValue* value,
- Handle<Map> map,
- HBasicBlock* true_target,
- HBasicBlock* false_target)
- : HUnaryControlInstruction(value, true_target, false_target),
- map_(map) {
- ASSERT(true_target != NULL);
- ASSERT(false_target != NULL);
- ASSERT(!map.is_null());
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- Handle<Map> map() const { return map_; }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(CompareMap)
-
- private:
- Handle<Map> map_;
-};
-
-
-class HReturn: public HTemplateControlInstruction<0, 2> {
- public:
- HReturn(HValue* value, HValue* context) {
- SetOperandAt(0, value);
- SetOperandAt(1, context);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- HValue* value() { return OperandAt(0); }
- HValue* context() { return OperandAt(1); }
-
- DECLARE_CONCRETE_INSTRUCTION(Return)
-};
-
-
-class HAbnormalExit: public HTemplateControlInstruction<0, 0> {
- public:
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(AbnormalExit)
-};
-
-
-class HUnaryOperation: public HTemplateInstruction<1> {
- public:
- explicit HUnaryOperation(HValue* value) {
- SetOperandAt(0, value);
- }
-
- static HUnaryOperation* cast(HValue* value) {
- return reinterpret_cast<HUnaryOperation*>(value);
- }
-
- HValue* value() const { return OperandAt(0); }
- virtual void PrintDataTo(StringStream* stream);
-};
-
-
-class HThrow: public HTemplateInstruction<2> {
- public:
- HThrow(HValue* context, HValue* value) {
- SetOperandAt(0, context);
- SetOperandAt(1, value);
- SetAllSideEffects();
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- HValue* context() { return OperandAt(0); }
- HValue* value() { return OperandAt(1); }
-
- DECLARE_CONCRETE_INSTRUCTION(Throw)
-};
-
-
-class HUseConst: public HUnaryOperation {
- public:
- explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(UseConst)
-};
-
-
-class HForceRepresentation: public HTemplateInstruction<1> {
- public:
- HForceRepresentation(HValue* value, Representation required_representation) {
- SetOperandAt(0, value);
- set_representation(required_representation);
- }
-
- HValue* value() { return OperandAt(0); }
-
- virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return representation(); // Same as the output representation.
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation)
-};
-
-
-class HChange: public HUnaryOperation {
- public:
- HChange(HValue* value,
- Representation to,
- bool is_truncating,
- bool deoptimize_on_undefined)
- : HUnaryOperation(value) {
- ASSERT(!value->representation().IsNone() && !to.IsNone());
- ASSERT(!value->representation().Equals(to));
- set_representation(to);
- set_type(HType::TaggedNumber());
- SetFlag(kUseGVN);
- if (deoptimize_on_undefined) SetFlag(kDeoptimizeOnUndefined);
- if (is_truncating) SetFlag(kTruncatingToInt32);
- if (to.IsTagged()) SetGVNFlag(kChangesNewSpacePromotion);
- }
-
- virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
- virtual HType CalculateInferredType();
- virtual HValue* Canonicalize();
-
- Representation from() const { return value()->representation(); }
- Representation to() const { return representation(); }
- bool deoptimize_on_undefined() const {
- return CheckFlag(kDeoptimizeOnUndefined);
- }
- bool deoptimize_on_minus_zero() const {
- return CheckFlag(kBailoutOnMinusZero);
- }
- virtual Representation RequiredInputRepresentation(int index) {
- return from();
- }
-
- virtual Range* InferRange(Zone* zone);
-
- virtual void PrintDataTo(StringStream* stream);
-
- DECLARE_CONCRETE_INSTRUCTION(Change)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- private:
- virtual bool IsDeletable() const {
- return !from().IsTagged() || value()->type().IsSmi();
- }
-};
-
-
-class HClampToUint8: public HUnaryOperation {
- public:
- explicit HClampToUint8(HValue* value)
- : HUnaryOperation(value) {
- set_representation(Representation::Integer32());
- SetFlag(kUseGVN);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
-enum RemovableSimulate {
- REMOVABLE_SIMULATE,
- FIXED_SIMULATE
-};
-
-
-class HSimulate: 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),
- removable_(removable) {}
- virtual ~HSimulate() {}
-
- virtual void PrintDataTo(StringStream* stream);
-
- bool HasAstId() const { return !ast_id_.IsNone(); }
- BailoutId ast_id() const { return ast_id_; }
- void set_ast_id(BailoutId id) {
- ASSERT(!HasAstId());
- ast_id_ = id;
- }
-
- int pop_count() const { return pop_count_; }
- const ZoneList<HValue*>* values() const { return &values_; }
- int GetAssignedIndexAt(int index) const {
- ASSERT(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);
- }
- virtual int OperandCount() { return values_.length(); }
- virtual HValue* OperandAt(int index) const { return values_[index]; }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- void MergeInto(HSimulate* other);
- bool is_candidate_for_removal() { return removable_ == REMOVABLE_SIMULATE; }
-
- DECLARE_CONCRETE_INSTRUCTION(Simulate)
-
-#ifdef DEBUG
- virtual void Verify();
-#endif
-
- protected:
- virtual void InternalSetOperandAt(int index, HValue* value) {
- 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);
- }
- BailoutId ast_id_;
- int pop_count_;
- ZoneList<HValue*> values_;
- ZoneList<int> assigned_indexes_;
- Zone* zone_;
- RemovableSimulate removable_;
-};
-
-
-class HStackCheck: public HTemplateInstruction<1> {
- public:
- enum Type {
- kFunctionEntry,
- kBackwardsBranch
- };
-
- HStackCheck(HValue* context, Type type) : type_(type) {
- SetOperandAt(0, context);
- SetGVNFlag(kChangesNewSpacePromotion);
- }
-
- HValue* context() { return OperandAt(0); }
-
- virtual Representation RequiredInputRepresentation(int index) {
- 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:
- Type type_;
-};
-
-
-enum InliningKind {
- NORMAL_RETURN, // Normal function/method call and return.
- DROP_EXTRA_ON_RETURN, // Drop an extra value 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 HEnterInlined: public HTemplateInstruction<0> {
- public:
- HEnterInlined(Handle<JSFunction> closure,
- int arguments_count,
- FunctionLiteral* function,
- InliningKind inlining_kind,
- Variable* arguments_var,
- ZoneList<HValue*>* arguments_values,
- bool undefined_receiver)
- : closure_(closure),
- arguments_count_(arguments_count),
- arguments_pushed_(false),
- function_(function),
- inlining_kind_(inlining_kind),
- arguments_var_(arguments_var),
- arguments_values_(arguments_values),
- undefined_receiver_(undefined_receiver) {
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- Handle<JSFunction> closure() const { return closure_; }
- 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_; }
- bool undefined_receiver() const { return undefined_receiver_; }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- Variable* arguments_var() { return arguments_var_; }
- ZoneList<HValue*>* arguments_values() { return arguments_values_; }
-
- DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
-
- private:
- Handle<JSFunction> closure_;
- int arguments_count_;
- bool arguments_pushed_;
- FunctionLiteral* function_;
- InliningKind inlining_kind_;
- Variable* arguments_var_;
- ZoneList<HValue*>* arguments_values_;
- bool undefined_receiver_;
-};
-
-
-class HLeaveInlined: public HTemplateInstruction<0> {
- public:
- HLeaveInlined() { }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(LeaveInlined)
-};
-
-
-class HPushArgument: public HUnaryOperation {
- public:
- explicit HPushArgument(HValue* value) : HUnaryOperation(value) {
- set_representation(Representation::Tagged());
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- HValue* argument() { return OperandAt(0); }
-
- DECLARE_CONCRETE_INSTRUCTION(PushArgument)
-};
-
-
-class HThisFunction: public HTemplateInstruction<0> {
- public:
- HThisFunction() {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(ThisFunction)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
-class HContext: public HTemplateInstruction<0> {
- public:
- HContext() {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Context)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
-class HOuterContext: public HUnaryOperation {
- public:
- explicit HOuterContext(HValue* inner) : HUnaryOperation(inner) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- }
-
- DECLARE_CONCRETE_INSTRUCTION(OuterContext);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
-class HDeclareGlobals: public HUnaryOperation {
- public:
- HDeclareGlobals(HValue* context,
- Handle<FixedArray> pairs,
- int flags)
- : HUnaryOperation(context),
- pairs_(pairs),
- flags_(flags) {
- set_representation(Representation::Tagged());
- SetAllSideEffects();
- }
-
- HValue* context() { return OperandAt(0); }
- Handle<FixedArray> pairs() const { return pairs_; }
- int flags() const { return flags_; }
-
- DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals)
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
- private:
- Handle<FixedArray> pairs_;
- int flags_;
-};
-
-
-class HGlobalObject: public HUnaryOperation {
- public:
- explicit HGlobalObject(HValue* context)
- : HUnaryOperation(context), qml_global_(false) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- DECLARE_CONCRETE_INSTRUCTION(GlobalObject)
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- bool qml_global() { return qml_global_; }
- void set_qml_global(bool v) { qml_global_ = v; }
-
- protected:
- virtual bool DataEquals(HValue* other) {
- HGlobalObject* o = HGlobalObject::cast(other);
- return o->qml_global_ == qml_global_;
- }
-
- private:
- virtual bool IsDeletable() const { return true; }
- bool qml_global_;
-};
-
-
-class HGlobalReceiver: public HUnaryOperation {
- public:
- explicit HGlobalReceiver(HValue* global_object)
- : HUnaryOperation(global_object) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- }
-
- DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver)
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
-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();
- }
-
- virtual HType CalculateInferredType() { return HType::Tagged(); }
-
- virtual int argument_count() const { return argument_count_; }
-
- virtual bool IsCall() { return true; }
-
- private:
- int argument_count_;
-};
-
-
-class HUnaryCall: public HCall<1> {
- public:
- HUnaryCall(HValue* value, int argument_count)
- : HCall<1>(argument_count) {
- SetOperandAt(0, value);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- HValue* value() { 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);
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- HValue* first() { return OperandAt(0); }
- HValue* second() { return OperandAt(1); }
-};
-
-
-class HInvokeFunction: public HBinaryCall {
- public:
- HInvokeFunction(HValue* context, HValue* function, int argument_count)
- : HBinaryCall(context, function, argument_count) {
- }
-
- HInvokeFunction(HValue* context,
- HValue* function,
- Handle<JSFunction> known_function,
- int argument_count)
- : HBinaryCall(context, function, argument_count),
- known_function_(known_function) {
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- HValue* context() { return first(); }
- HValue* function() { return second(); }
- Handle<JSFunction> known_function() { return known_function_; }
-
- DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
-
- private:
- Handle<JSFunction> known_function_;
-};
-
-
-class HCallConstantFunction: public HCall<0> {
- public:
- HCallConstantFunction(Handle<JSFunction> function, int argument_count)
- : HCall<0>(argument_count), function_(function) { }
-
- Handle<JSFunction> function() const { return function_; }
-
- bool IsApplyFunction() const {
- return function_->code() ==
- Isolate::Current()->builtins()->builtin(Builtins::kFunctionApply);
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction)
-
- private:
- Handle<JSFunction> function_;
-};
-
-
-class HCallKeyed: public HBinaryCall {
- public:
- HCallKeyed(HValue* context, HValue* key, int argument_count)
- : HBinaryCall(context, key, argument_count) {
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- HValue* context() { return first(); }
- HValue* key() { return second(); }
-
- DECLARE_CONCRETE_INSTRUCTION(CallKeyed)
-};
-
-
-class HCallNamed: public HUnaryCall {
- public:
- HCallNamed(HValue* context, Handle<String> name, int argument_count)
- : HUnaryCall(context, argument_count), name_(name) {
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- HValue* context() { return value(); }
- Handle<String> name() const { return name_; }
-
- DECLARE_CONCRETE_INSTRUCTION(CallNamed)
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- private:
- Handle<String> name_;
-};
-
-
-class HCallFunction: public HBinaryCall {
- public:
- HCallFunction(HValue* context, HValue* function, int argument_count)
- : HBinaryCall(context, function, argument_count) {
- }
-
- HValue* context() { return first(); }
- HValue* function() { return second(); }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(CallFunction)
-};
-
-
-class HCallGlobal: public HUnaryCall {
- public:
- HCallGlobal(HValue* context, Handle<String> name, int argument_count)
- : HUnaryCall(context, argument_count), name_(name), qml_global_(false) {
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- HValue* context() { return value(); }
- Handle<String> name() const { return name_; }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- bool qml_global() { return qml_global_; }
- void set_qml_global(bool v) { qml_global_ = v; }
-
- DECLARE_CONCRETE_INSTRUCTION(CallGlobal)
-
- private:
- Handle<String> name_;
- bool qml_global_;
-};
-
-
-class HCallKnownGlobal: public HCall<0> {
- public:
- HCallKnownGlobal(Handle<JSFunction> target, int argument_count)
- : HCall<0>(argument_count), target_(target) { }
-
- virtual void PrintDataTo(StringStream* stream);
-
- Handle<JSFunction> target() const { return target_; }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal)
-
- private:
- Handle<JSFunction> target_;
-};
-
-
-class HCallNew: public HBinaryCall {
- public:
- HCallNew(HValue* context, HValue* constructor, int argument_count)
- : HBinaryCall(context, constructor, argument_count) {
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- HValue* context() { return first(); }
- HValue* constructor() { return second(); }
-
- DECLARE_CONCRETE_INSTRUCTION(CallNew)
-};
-
-
-class HCallNewArray: public HCallNew {
- public:
- HCallNewArray(HValue* context, HValue* constructor, int argument_count,
- Handle<JSGlobalPropertyCell> type_cell)
- : HCallNew(context, constructor, argument_count),
- type_cell_(type_cell) {
- }
-
- Handle<JSGlobalPropertyCell> property_cell() const {
- return type_cell_;
- }
-
- DECLARE_CONCRETE_INSTRUCTION(CallNewArray)
-
- private:
- Handle<JSGlobalPropertyCell> type_cell_;
-};
-
-
-class HCallRuntime: public HCall<1> {
- public:
- HCallRuntime(HValue* context,
- Handle<String> name,
- const Runtime::Function* c_function,
- int argument_count)
- : HCall<1>(argument_count), c_function_(c_function), name_(name) {
- SetOperandAt(0, context);
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- HValue* context() { return OperandAt(0); }
- const Runtime::Function* function() const { return c_function_; }
- Handle<String> name() const { return name_; }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(CallRuntime)
-
- private:
- const Runtime::Function* c_function_;
- Handle<String> name_;
-};
-
-
-class HJSArrayLength: public HTemplateInstruction<2> {
- public:
- HJSArrayLength(HValue* value, HValue* typecheck,
- HType type = HType::Tagged()) {
- set_type(type);
- // The length of an array is stored as a tagged value in the array
- // object. It is guaranteed to be 32 bit integer, but it can be
- // represented as either a smi or heap number.
- SetOperandAt(0, value);
- SetOperandAt(1, typecheck != NULL ? typecheck : value);
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnArrayLengths);
- SetGVNFlag(kDependsOnMaps);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- HValue* value() { return OperandAt(0); }
- HValue* typecheck() {
- ASSERT(HasTypeCheck());
- return OperandAt(1);
- }
- bool HasTypeCheck() const { return OperandAt(0) != OperandAt(1); }
-
- DECLARE_CONCRETE_INSTRUCTION(JSArrayLength)
-
- protected:
- virtual bool DataEquals(HValue* other_raw) { return true; }
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
-class HFixedArrayBaseLength: public HUnaryOperation {
- public:
- explicit HFixedArrayBaseLength(HValue* value) : HUnaryOperation(value) {
- set_type(HType::Smi());
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnArrayLengths);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(FixedArrayBaseLength)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
-class HMapEnumLength: public HUnaryOperation {
- public:
- explicit HMapEnumLength(HValue* value) : HUnaryOperation(value) {
- set_type(HType::Smi());
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnMaps);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(MapEnumLength)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
-class HElementsKind: public HUnaryOperation {
- public:
- explicit HElementsKind(HValue* value) : HUnaryOperation(value) {
- set_representation(Representation::Integer32());
- SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnElementsKind);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(ElementsKind)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
-class HBitNot: public HUnaryOperation {
- public:
- explicit HBitNot(HValue* value) : HUnaryOperation(value) {
- set_representation(Representation::Integer32());
- SetFlag(kUseGVN);
- SetFlag(kTruncatingToInt32);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Integer32();
- }
- virtual Representation observed_input_representation(int index) {
- return Representation::Integer32();
- }
- virtual HType CalculateInferredType();
-
- virtual HValue* Canonicalize();
-
- DECLARE_CONCRETE_INSTRUCTION(BitNot)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
-class HUnaryMathOperation: public HTemplateInstruction<2> {
- public:
- static HInstruction* New(Zone* zone,
- HValue* context,
- HValue* value,
- BuiltinFunctionId op);
-
- HValue* context() { return OperandAt(0); }
- HValue* value() { return OperandAt(1); }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual HType CalculateInferredType();
-
- virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
-
- virtual Representation RequiredInputRepresentation(int index) {
- if (index == 0) {
- return Representation::Tagged();
- } else {
- switch (op_) {
- case kMathFloor:
- case kMathRound:
- case kMathSqrt:
- case kMathPowHalf:
- case kMathLog:
- case kMathExp:
- case kMathSin:
- case kMathCos:
- case kMathTan:
- return Representation::Double();
- case kMathAbs:
- return representation();
- default:
- UNREACHABLE();
- return Representation::None();
- }
- }
- }
-
- virtual HValue* Canonicalize();
-
- BuiltinFunctionId op() const { return op_; }
- const char* OpName() const;
-
- DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)
-
- protected:
- virtual bool DataEquals(HValue* other) {
- HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
- return op_ == b->op();
- }
-
- private:
- HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
- : op_(op) {
- SetOperandAt(0, context);
- SetOperandAt(1, value);
- switch (op) {
- case kMathFloor:
- case kMathRound:
- case kMathCeil:
- set_representation(Representation::Integer32());
- break;
- case kMathAbs:
- // Not setting representation here: it is None intentionally.
- SetFlag(kFlexibleRepresentation);
- SetGVNFlag(kChangesNewSpacePromotion);
- break;
- case kMathSqrt:
- case kMathPowHalf:
- case kMathLog:
- case kMathSin:
- case kMathCos:
- case kMathTan:
- set_representation(Representation::Double());
- SetGVNFlag(kChangesNewSpacePromotion);
- break;
- case kMathExp:
- set_representation(Representation::Double());
- break;
- default:
- UNREACHABLE();
- }
- SetFlag(kUseGVN);
- }
-
- virtual bool IsDeletable() const { return true; }
-
- BuiltinFunctionId op_;
-};
-
-
-class HLoadElements: public HTemplateInstruction<2> {
- public:
- HLoadElements(HValue* value, HValue* typecheck) {
- SetOperandAt(0, value);
- SetOperandAt(1, typecheck != NULL ? typecheck : value);
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnElementsPointer);
- }
-
- HValue* value() { return OperandAt(0); }
- HValue* typecheck() {
- ASSERT(HasTypeCheck());
- return OperandAt(1);
- }
- bool HasTypeCheck() const { return OperandAt(0) != OperandAt(1); }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(LoadElements)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
-class HLoadExternalArrayPointer: public HUnaryOperation {
- public:
- explicit HLoadExternalArrayPointer(HValue* value)
- : HUnaryOperation(value) {
- set_representation(Representation::External());
- // The result of this instruction is idempotent as long as its inputs don't
- // change. The external array of a specialized array elements object cannot
- // change once set, so it's no necessary to introduce any additional
- // dependencies on top of the inputs.
- SetFlag(kUseGVN);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
-class HCheckMaps: public HTemplateInstruction<2> {
- public:
- HCheckMaps(HValue* value, Handle<Map> map, Zone* zone,
- HValue* typecheck = NULL) {
- SetOperandAt(0, value);
- // If callers don't depend on a typecheck, they can pass in NULL. In that
- // case we use a copy of the |value| argument as a dummy value.
- SetOperandAt(1, typecheck != NULL ? typecheck : value);
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetFlag(kTrackSideEffectDominators);
- SetGVNFlag(kDependsOnMaps);
- SetGVNFlag(kDependsOnElementsKind);
- map_set()->Add(map, zone);
- }
- HCheckMaps(HValue* value, SmallMapList* maps, Zone* zone) {
- SetOperandAt(0, value);
- SetOperandAt(1, value);
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetFlag(kTrackSideEffectDominators);
- SetGVNFlag(kDependsOnMaps);
- SetGVNFlag(kDependsOnElementsKind);
- for (int i = 0; i < maps->length(); i++) {
- map_set()->Add(maps->at(i), zone);
- }
- map_set()->Sort();
- }
-
- static HCheckMaps* NewWithTransitions(HValue* object, Handle<Map> map,
- Zone* zone) {
- HCheckMaps* check_map = new(zone) HCheckMaps(object, map, zone);
- SmallMapList* map_set = check_map->map_set();
-
- // Since transitioned elements maps of the initial map don't fail the map
- // check, the CheckMaps instruction doesn't need to depend on ElementsKinds.
- check_map->ClearGVNFlag(kDependsOnElementsKind);
-
- ElementsKind kind = map->elements_kind();
- bool packed = IsFastPackedElementsKind(kind);
- while (CanTransitionToMoreGeneralFastElementsKind(kind, packed)) {
- kind = GetNextMoreGeneralFastElementsKind(kind, packed);
- Map* transitioned_map =
- map->LookupElementsTransitionMap(kind);
- if (transitioned_map) {
- map_set->Add(Handle<Map>(transitioned_map), zone);
- }
- };
- map_set->Sort();
- return check_map;
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
- virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator);
- virtual void PrintDataTo(StringStream* stream);
- virtual HType CalculateInferredType();
-
- HValue* value() { return OperandAt(0); }
- SmallMapList* map_set() { return &map_set_; }
-
- DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
-
- protected:
- virtual bool DataEquals(HValue* other) {
- HCheckMaps* b = HCheckMaps::cast(other);
- // Relies on the fact that map_set has been sorted before.
- if (map_set()->length() != b->map_set()->length()) return false;
- for (int i = 0; i < map_set()->length(); i++) {
- if (!map_set()->at(i).is_identical_to(b->map_set()->at(i))) return false;
- }
- return true;
- }
-
- private:
- SmallMapList map_set_;
-};
-
-
-class HCheckFunction: public HUnaryOperation {
- public:
- HCheckFunction(HValue* value, Handle<JSFunction> function)
- : HUnaryOperation(value), target_(function) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- target_in_new_space_ = Isolate::Current()->heap()->InNewSpace(*function);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
- virtual void PrintDataTo(StringStream* stream);
- virtual HType CalculateInferredType();
-
-#ifdef DEBUG
- virtual void Verify();
-#endif
-
- Handle<JSFunction> target() const { return target_; }
- bool target_in_new_space() const { return target_in_new_space_; }
-
- DECLARE_CONCRETE_INSTRUCTION(CheckFunction)
-
- protected:
- virtual bool DataEquals(HValue* other) {
- HCheckFunction* b = HCheckFunction::cast(other);
- return target_.is_identical_to(b->target());
- }
-
- private:
- Handle<JSFunction> target_;
- bool target_in_new_space_;
-};
-
-
-class HCheckInstanceType: public HUnaryOperation {
- public:
- static HCheckInstanceType* NewIsSpecObject(HValue* value, Zone* zone) {
- return new(zone) HCheckInstanceType(value, IS_SPEC_OBJECT);
- }
- static HCheckInstanceType* NewIsJSArray(HValue* value, Zone* zone) {
- return new(zone) HCheckInstanceType(value, IS_JS_ARRAY);
- }
- static HCheckInstanceType* NewIsString(HValue* value, Zone* zone) {
- return new(zone) HCheckInstanceType(value, IS_STRING);
- }
- static HCheckInstanceType* NewIsInternalizedString(
- HValue* value, Zone* zone) {
- return new(zone) HCheckInstanceType(value, IS_INTERNALIZED_STRING);
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- virtual HValue* Canonicalize();
-
- bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
- void GetCheckInterval(InstanceType* first, InstanceType* last);
- void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);
-
- 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.
- virtual bool DataEquals(HValue* other) {
- HCheckInstanceType* b = HCheckInstanceType::cast(other);
- return check_ == b->check_;
- }
-
- private:
- enum Check {
- IS_SPEC_OBJECT,
- IS_JS_ARRAY,
- IS_STRING,
- IS_INTERNALIZED_STRING,
- LAST_INTERVAL_CHECK = IS_JS_ARRAY
- };
-
- const char* GetCheckName();
-
- HCheckInstanceType(HValue* value, Check check)
- : HUnaryOperation(value), check_(check) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- }
-
- const Check check_;
-};
-
-
-class HCheckNonSmi: public HUnaryOperation {
- public:
- explicit HCheckNonSmi(HValue* value) : HUnaryOperation(value) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- virtual HType CalculateInferredType();
-
-#ifdef DEBUG
- virtual void Verify();
-#endif
-
- virtual HValue* Canonicalize() {
- HType value_type = value()->type();
- if (!value_type.IsUninitialized() &&
- (value_type.IsHeapNumber() ||
- value_type.IsString() ||
- value_type.IsBoolean() ||
- value_type.IsNonPrimitive())) {
- return NULL;
- }
- return this;
- }
-
- DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-};
-
-
-class HCheckPrototypeMaps: public HTemplateInstruction<0> {
- public:
- HCheckPrototypeMaps(Handle<JSObject> prototype,
- Handle<JSObject> holder,
- Zone* zone) : prototypes_(2, zone), maps_(2, zone) {
- SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnMaps);
- // Keep a list of all objects on the prototype chain up to the holder
- // and the expected maps.
- while (true) {
- prototypes_.Add(prototype, zone);
- maps_.Add(Handle<Map>(prototype->map()), zone);
- if (prototype.is_identical_to(holder)) break;
- prototype = Handle<JSObject>(JSObject::cast(prototype->GetPrototype()));
- }
- }
-
- ZoneList<Handle<JSObject> >* prototypes() { return &prototypes_; }
-
- ZoneList<Handle<Map> >* maps() { return &maps_; }
-
- DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps)
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual intptr_t Hashcode() {
- ASSERT_ALLOCATION_DISABLED;
- // Dereferencing to use the object's raw address for hashing is safe.
- AllowHandleDereference allow_handle_deref(isolate());
- intptr_t hash = 0;
- for (int i = 0; i < prototypes_.length(); i++) {
- hash = 17 * hash + reinterpret_cast<intptr_t>(*prototypes_[i]);
- hash = 17 * hash + reinterpret_cast<intptr_t>(*maps_[i]);
- }
- return hash;
- }
-
- bool CanOmitPrototypeChecks() {
- for (int i = 0; i < maps()->length(); i++) {
- if (!maps()->at(i)->CanOmitPrototypeChecks()) return false;
- }
- return true;
- }
-
- protected:
- virtual bool DataEquals(HValue* other) {
- HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
-#ifdef DEBUG
- if (prototypes_.length() != b->prototypes()->length()) return false;
- for (int i = 0; i < prototypes_.length(); i++) {
- if (!prototypes_[i].is_identical_to(b->prototypes()->at(i))) return false;
- if (!maps_[i].is_identical_to(b->maps()->at(i))) return false;
- }
- return true;
-#else
- return prototypes_.first().is_identical_to(b->prototypes()->first()) &&
- prototypes_.last().is_identical_to(b->prototypes()->last());
-#endif // DEBUG
- }
-
- private:
- ZoneList<Handle<JSObject> > prototypes_;
- ZoneList<Handle<Map> > maps_;
-};
-
-
-class HCheckSmi: public HUnaryOperation {
- public:
- explicit HCheckSmi(HValue* value) : HUnaryOperation(value) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
- virtual HType CalculateInferredType();
-
-#ifdef DEBUG
- virtual void Verify();
-#endif
-
- DECLARE_CONCRETE_INSTRUCTION(CheckSmi)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-};
-
-
-class HCheckSmiOrInt32: public HUnaryOperation {
- public:
- explicit HCheckSmiOrInt32(HValue* value) : HUnaryOperation(value) {
- SetFlag(kFlexibleRepresentation);
- SetFlag(kUseGVN);
- }
-
- virtual int RedefinedOperandIndex() { return 0; }
- virtual Representation RequiredInputRepresentation(int index) {
- return representation();
- }
- virtual void InferRepresentation(HInferRepresentation* h_infer);
-
- virtual Representation observed_input_representation(int index) {
- return Representation::Integer32();
- }
-
- virtual HValue* Canonicalize() {
- if (representation().IsTagged() && !type().IsSmi()) {
- return this;
- } else {
- return value();
- }
- }
-
- DECLARE_CONCRETE_INSTRUCTION(CheckSmiOrInt32)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-};
-
-
-class HPhi: public HValue {
- public:
- HPhi(int merged_index, Zone* zone)
- : inputs_(2, zone),
- merged_index_(merged_index),
- phi_id_(-1),
- is_live_(false),
- is_convertible_to_integer_(true) {
- for (int i = 0; i < Representation::kNumRepresentations; i++) {
- non_phi_uses_[i] = 0;
- indirect_uses_[i] = 0;
- }
- ASSERT(merged_index >= 0);
- SetFlag(kFlexibleRepresentation);
- }
-
- virtual Representation RepresentationFromInputs();
-
- virtual Range* InferRange(Zone* zone);
- virtual void InferRepresentation(HInferRepresentation* h_infer);
- Representation RepresentationObservedByAllNonPhiUses();
- Representation RepresentationFromUseRequirements();
- virtual Representation RequiredInputRepresentation(int index) {
- return representation();
- }
- virtual HType CalculateInferredType();
- virtual int OperandCount() { return inputs_.length(); }
- virtual HValue* OperandAt(int index) const { return inputs_[index]; }
- HValue* GetRedundantReplacement();
- void AddInput(HValue* value);
- bool HasRealUses();
-
- bool IsReceiver() { return merged_index_ == 0; }
-
- int merged_index() const { return merged_index_; }
-
- virtual void AddInformativeDefinitions();
-
- virtual void PrintTo(StringStream* stream);
-
-#ifdef DEBUG
- virtual void Verify();
-#endif
-
- void InitRealUses(int id);
- void AddNonPhiUsesFrom(HPhi* other);
- void AddIndirectUsesTo(int* use_count);
-
- int tagged_non_phi_uses() const {
- return non_phi_uses_[Representation::kTagged];
- }
- int int32_non_phi_uses() const {
- return non_phi_uses_[Representation::kInteger32];
- }
- int double_non_phi_uses() const {
- return non_phi_uses_[Representation::kDouble];
- }
- int tagged_indirect_uses() const {
- return indirect_uses_[Representation::kTagged];
- }
- int int32_indirect_uses() const {
- return indirect_uses_[Representation::kInteger32];
- }
- int double_indirect_uses() const {
- return indirect_uses_[Representation::kDouble];
- }
- int phi_id() { return phi_id_; }
- bool is_live() { return is_live_; }
- void set_is_live(bool b) { is_live_ = b; }
-
- static HPhi* cast(HValue* value) {
- ASSERT(value->IsPhi());
- return reinterpret_cast<HPhi*>(value);
- }
- virtual Opcode opcode() const { return HValue::kPhi; }
-
- virtual bool IsConvertibleToInteger() const {
- return is_convertible_to_integer_;
- }
-
- void set_is_convertible_to_integer(bool b) {
- is_convertible_to_integer_ = b;
- }
-
- bool AllOperandsConvertibleToInteger() {
- for (int i = 0; i < OperandCount(); ++i) {
- if (!OperandAt(i)->IsConvertibleToInteger()) {
- if (FLAG_trace_representation) {
- HValue* input = OperandAt(i);
- PrintF("#%d %s: Input #%d %s at %d is NCTI\n",
- id(), Mnemonic(), input->id(), input->Mnemonic(), i);
- }
- return false;
- }
- }
- return true;
- }
-
- protected:
- virtual void DeleteFromGraph();
- virtual void InternalSetOperandAt(int index, HValue* value) {
- inputs_[index] = value;
- }
-
- virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* other);
-
- private:
- ZoneList<HValue*> inputs_;
- int merged_index_;
-
- int non_phi_uses_[Representation::kNumRepresentations];
- int indirect_uses_[Representation::kNumRepresentations];
- int phi_id_;
- bool is_live_;
- bool is_convertible_to_integer_;
-};
-
-
-class HInductionVariableAnnotation : public HUnaryOperation {
- public:
- static HInductionVariableAnnotation* AddToGraph(HPhi* phi,
- NumericRelation relation,
- int operand_index);
-
- NumericRelation relation() { return relation_; }
- HValue* induction_base() { return phi_->OperandAt(operand_index_); }
-
- virtual int RedefinedOperandIndex() { return 0; }
- virtual bool IsPurelyInformativeDefinition() { return true; }
- virtual Representation RequiredInputRepresentation(int index) {
- return representation();
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual bool IsRelationTrueInternal(NumericRelation other_relation,
- HValue* other_related_value) {
- if (induction_base() == other_related_value) {
- return relation().Implies(other_relation);
- } else {
- return false;
- }
- }
-
- DECLARE_CONCRETE_INSTRUCTION(InductionVariableAnnotation)
-
- private:
- HInductionVariableAnnotation(HPhi* phi,
- NumericRelation relation,
- int operand_index)
- : HUnaryOperation(phi),
- phi_(phi), relation_(relation), operand_index_(operand_index) {
- set_representation(phi->representation());
- }
-
- // We need to store the phi both here and in the instruction operand because
- // the operand can change if a new idef of the phi is added between the phi
- // and this instruction (inserting an idef updates every use).
- HPhi* phi_;
- NumericRelation relation_;
- int operand_index_;
-};
-
-
-class HArgumentsObject: public HTemplateInstruction<0> {
- public:
- HArgumentsObject() {
- set_representation(Representation::Tagged());
- SetFlag(kIsArguments);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
-class HConstant: public HTemplateInstruction<0> {
- public:
- HConstant(Handle<Object> handle, Representation r);
- HConstant(int32_t value, Representation r);
- HConstant(double value, Representation r);
-
- Handle<Object> handle() {
- if (handle_.is_null()) {
- handle_ = FACTORY->NewNumber(double_value_, TENURED);
- }
- ASSERT(has_int32_value_ || !handle_->IsSmi());
- return handle_;
- }
-
- bool InOldSpace() const { return !HEAP->InNewSpace(*handle_); }
-
- bool ImmortalImmovable() const {
- if (has_int32_value_) {
- return false;
- }
- if (has_double_value_) {
- if (BitCast<int64_t>(double_value_) == BitCast<int64_t>(-0.0) ||
- isnan(double_value_)) {
- return true;
- }
- return false;
- }
-
- ASSERT(!handle_.is_null());
- Heap* heap = isolate()->heap();
- // We should have handled minus_zero_value and nan_value in the
- // has_double_value_ clause above.
- // Dereferencing is safe to compare against singletons.
- AllowHandleDereference allow_handle_deref(isolate());
- ASSERT(*handle_ != heap->minus_zero_value());
- ASSERT(*handle_ != heap->nan_value());
- return *handle_ == heap->undefined_value() ||
- *handle_ == heap->null_value() ||
- *handle_ == heap->true_value() ||
- *handle_ == heap->false_value() ||
- *handle_ == heap->the_hole_value() ||
- *handle_ == heap->empty_string();
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- virtual bool IsConvertibleToInteger() const {
- return has_int32_value_;
- }
-
- virtual bool EmitAtUses() { return !representation().IsDouble(); }
- virtual void PrintDataTo(StringStream* stream);
- virtual HType CalculateInferredType();
- bool IsInteger() { return handle()->IsSmi(); }
- HConstant* CopyToRepresentation(Representation r, Zone* zone) const;
- HConstant* CopyToTruncatedInt32(Zone* zone) const;
- bool HasInteger32Value() const { return has_int32_value_; }
- int32_t Integer32Value() const {
- ASSERT(HasInteger32Value());
- return int32_value_;
- }
- bool HasSmiValue() const {
- return HasInteger32Value() && Smi::IsValid(Integer32Value());
- }
- bool HasDoubleValue() const { return has_double_value_; }
- double DoubleValue() const {
- ASSERT(HasDoubleValue());
- return double_value_;
- }
- bool HasNumberValue() const { return has_double_value_; }
- int32_t NumberValueAsInteger32() const {
- ASSERT(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 (has_double_value_ || has_int32_value_) return false;
- ASSERT(!handle_.is_null());
- return handle_->IsString();
- }
- Handle<String> StringValue() const {
- ASSERT(HasStringValue());
- return Handle<String>::cast(handle_);
- }
-
- bool ToBoolean();
-
- bool IsUint32() {
- return HasInteger32Value() && (Integer32Value() >= 0);
- }
-
- virtual intptr_t Hashcode() {
- ASSERT_ALLOCATION_DISABLED;
- intptr_t hash;
-
- if (has_int32_value_) {
- hash = static_cast<intptr_t>(int32_value_);
- } else if (has_double_value_) {
- hash = static_cast<intptr_t>(BitCast<int64_t>(double_value_));
- } else {
- ASSERT(!handle_.is_null());
- // Dereferencing to use the object's raw address for hashing is safe.
- AllowHandleDereference allow_handle_deref(isolate());
- hash = reinterpret_cast<intptr_t>(*handle_);
- }
-
- return hash;
- }
-
-#ifdef DEBUG
- virtual void Verify() { }
-#endif
-
- DECLARE_CONCRETE_INSTRUCTION(Constant)
-
- protected:
- virtual Range* InferRange(Zone* zone);
-
- virtual bool DataEquals(HValue* other) {
- HConstant* other_constant = HConstant::cast(other);
- if (has_int32_value_) {
- return other_constant->has_int32_value_ &&
- int32_value_ == other_constant->int32_value_;
- } else if (has_double_value_) {
- return other_constant->has_double_value_ &&
- BitCast<int64_t>(double_value_) ==
- BitCast<int64_t>(other_constant->double_value_);
- } else {
- ASSERT(!handle_.is_null());
- return !other_constant->handle_.is_null() &&
- handle_.is_identical_to(other_constant->handle_);
- }
- }
-
- private:
- void Initialize(Representation r);
-
- virtual bool IsDeletable() const { return true; }
-
- // If this is a numerical constant, handle_ either points to to the
- // HeapObject the constant originated from or is null. If the
- // constant is non-numeric, handle_ always points to a valid
- // constant HeapObject.
- Handle<Object> handle_;
-
- // We store the HConstant in the most specific form safely possible.
- // The two flags, has_int32_value_ and has_double_value_ tell us if
- // int32_value_ and double_value_ hold valid, safe representations
- // of the constant. has_int32_value_ implies has_double_value_ but
- // not the converse.
- bool has_int32_value_ : 1;
- bool has_double_value_ : 1;
- int32_t int32_value_;
- double double_value_;
-};
-
-
-class HBinaryOperation: public HTemplateInstruction<3> {
- public:
- HBinaryOperation(HValue* context, HValue* left, HValue* right)
- : observed_output_representation_(Representation::None()) {
- ASSERT(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() { return OperandAt(0); }
- HValue* left() { return OperandAt(1); }
- HValue* right() { return OperandAt(2); }
-
- // TODO(kasperl): Move these helpers to the IA-32 Lithium
- // instruction sequence builder.
- HValue* LeastConstantOperand() {
- if (IsCommutative() && left()->IsConstant()) return right();
- return left();
- }
-
- HValue* MostConstantOperand() {
- if (IsCommutative() && left()->IsConstant()) return left();
- return right();
- }
-
- void set_observed_input_representation(Representation left,
- Representation right) {
- observed_input_representation_[0] = left;
- observed_input_representation_[1] = right;
- }
-
- virtual void initialize_output_representation(Representation observed) {
- observed_output_representation_ = observed;
- }
-
- virtual Representation observed_input_representation(int index) {
- if (index == 0) return Representation::Tagged();
- return observed_input_representation_[index - 1];
- }
-
- virtual void InferRepresentation(HInferRepresentation* h_infer);
- virtual Representation RepresentationFromInputs();
- virtual void AssumeRepresentation(Representation r);
-
- virtual bool IsCommutative() const { return false; }
-
- virtual void PrintDataTo(StringStream* stream);
-
- DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation)
-
- private:
- Representation observed_input_representation_[2];
- Representation observed_output_representation_;
-};
-
-
-class HWrapReceiver: public HTemplateInstruction<2> {
- public:
- HWrapReceiver(HValue* receiver, HValue* function) {
- set_representation(Representation::Tagged());
- SetOperandAt(0, receiver);
- SetOperandAt(1, function);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- HValue* receiver() { return OperandAt(0); }
- HValue* function() { return OperandAt(1); }
-
- virtual HValue* Canonicalize();
-
- virtual void PrintDataTo(StringStream* stream);
-
- DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
-};
-
-
-class HApplyArguments: public HTemplateInstruction<4> {
- public:
- 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();
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- // 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)
-};
-
-
-class HArgumentsElements: public HTemplateInstruction<0> {
- public:
- 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);
- }
-
- DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- bool from_inlined() const { return from_inlined_; }
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- private:
- virtual bool IsDeletable() const { return true; }
-
- bool from_inlined_;
-};
-
-
-class HArgumentsLength: public HUnaryOperation {
- public:
- explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
- set_representation(Representation::Integer32());
- SetFlag(kUseGVN);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
-class HAccessArgumentsAt: public HTemplateInstruction<3> {
- public:
- HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetOperandAt(0, arguments);
- SetOperandAt(1, length);
- SetOperandAt(2, index);
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual Representation RequiredInputRepresentation(int index) {
- // The arguments elements is considered tagged.
- return index == 0
- ? Representation::Tagged()
- : Representation::Integer32();
- }
-
- HValue* arguments() { return OperandAt(0); }
- HValue* length() { return OperandAt(1); }
- HValue* index() { return OperandAt(2); }
-
- DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)
-
- virtual bool DataEquals(HValue* other) { return true; }
-};
-
-
-enum BoundsCheckKeyMode {
- DONT_ALLOW_SMI_KEY,
- ALLOW_SMI_KEY
-};
-
-
-class HBoundsCheck: public HTemplateInstruction<2> {
- public:
- // Normally HBoundsCheck should be created using the
- // HGraphBuilder::AddBoundsCheck() helper, which also guards the index with
- // a HCheckSmiOrInt32 check.
- // 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,
- BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY,
- Representation r = Representation::None())
- : key_mode_(key_mode), skip_check_(false) {
- SetOperandAt(0, index);
- SetOperandAt(1, length);
- if (r.IsNone()) {
- // In the normal compilation pipeline the representation is flexible
- // (see InferRepresentation).
- SetFlag(kFlexibleRepresentation);
- } else {
- // When compiling stubs we want to set the representation explicitly
- // so the compilation pipeline can skip the HInferRepresentation phase.
- set_representation(r);
- }
- SetFlag(kUseGVN);
- }
-
- bool skip_check() { return skip_check_; }
- void set_skip_check(bool skip_check) { skip_check_ = skip_check; }
-
- virtual Representation RequiredInputRepresentation(int arg_index) {
- return representation();
- }
- virtual Representation observed_input_representation(int index) {
- return Representation::Integer32();
- }
-
- virtual bool IsRelationTrueInternal(NumericRelation relation,
- HValue* related_value);
-
- virtual void PrintDataTo(StringStream* stream);
- virtual void InferRepresentation(HInferRepresentation* h_infer);
-
- HValue* index() { return OperandAt(0); }
- HValue* length() { return OperandAt(1); }
-
- virtual int RedefinedOperandIndex() { return 0; }
- virtual bool IsPurelyInformativeDefinition() { return skip_check(); }
- virtual void AddInformativeDefinitions();
-
- DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
- BoundsCheckKeyMode key_mode_;
- bool skip_check_;
-};
-
-
-class HBitwiseBinaryOperation: public HBinaryOperation {
- public:
- HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right)
- : HBinaryOperation(context, left, right) {
- SetFlag(kFlexibleRepresentation);
- SetFlag(kTruncatingToInt32);
- SetAllSideEffects();
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return index == 0
- ? Representation::Tagged()
- : representation();
- }
-
- virtual void RepresentationChanged(Representation to) {
- if (!to.IsTagged()) {
- ASSERT(to.IsInteger32());
- ClearAllSideEffects();
- SetFlag(kUseGVN);
- } else {
- SetAllSideEffects();
- ClearFlag(kUseGVN);
- }
- }
-
- virtual void UpdateRepresentation(Representation new_rep,
- HInferRepresentation* h_infer,
- const char* reason) {
- // We only generate either int32 or generic tagged bitwise operations.
- if (new_rep.IsDouble()) new_rep = Representation::Integer32();
- HValue::UpdateRepresentation(new_rep, h_infer, reason);
- }
-
- virtual void initialize_output_representation(Representation observed) {
- if (observed.IsDouble()) observed = Representation::Integer32();
- HBinaryOperation::initialize_output_representation(observed);
- }
-
- virtual HType CalculateInferredType();
-
- DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
-class HMathFloorOfDiv: public HBinaryOperation {
- public:
- HMathFloorOfDiv(HValue* context, HValue* left, HValue* right)
- : HBinaryOperation(context, left, right) {
- set_representation(Representation::Integer32());
- SetFlag(kUseGVN);
- SetFlag(kCanOverflow);
- if (!right->IsConstant()) {
- SetFlag(kCanBeDivByZero);
- }
- }
-
- virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Integer32();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
-class HArithmeticBinaryOperation: public HBinaryOperation {
- public:
- HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right)
- : HBinaryOperation(context, left, right) {
- SetAllSideEffects();
- SetFlag(kFlexibleRepresentation);
- }
-
- virtual void RepresentationChanged(Representation to) {
- if (to.IsTagged()) {
- SetAllSideEffects();
- ClearFlag(kUseGVN);
- } else {
- ClearAllSideEffects();
- SetFlag(kUseGVN);
- }
- }
-
- virtual HType CalculateInferredType();
- virtual Representation RequiredInputRepresentation(int index) {
- return index == 0
- ? Representation::Tagged()
- : representation();
- }
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
-class HCompareGeneric: public HBinaryOperation {
- public:
- HCompareGeneric(HValue* context,
- HValue* left,
- HValue* right,
- Token::Value token)
- : HBinaryOperation(context, left, right), token_(token) {
- ASSERT(Token::IsCompareOp(token));
- set_representation(Representation::Tagged());
- SetAllSideEffects();
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return index == 0
- ? Representation::Tagged()
- : representation();
- }
-
- Token::Value token() const { return token_; }
- virtual void PrintDataTo(StringStream* stream);
-
- virtual HType CalculateInferredType();
-
- DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
-
- private:
- Token::Value token_;
-};
-
-
-class HCompareIDAndBranch: public HTemplateControlInstruction<2, 2> {
- public:
- HCompareIDAndBranch(HValue* left, HValue* right, Token::Value token)
- : token_(token) {
- SetFlag(kFlexibleRepresentation);
- ASSERT(Token::IsCompareOp(token));
- SetOperandAt(0, left);
- SetOperandAt(1, right);
- }
-
- HValue* left() { return OperandAt(0); }
- HValue* right() { 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(HInferRepresentation* h_infer);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return representation();
- }
- virtual Representation observed_input_representation(int index) {
- return observed_input_representation_[index];
- }
- virtual void PrintDataTo(StringStream* stream);
-
- virtual void AddInformativeDefinitions();
-
- DECLARE_CONCRETE_INSTRUCTION(CompareIDAndBranch)
-
- private:
- Representation observed_input_representation_[2];
- Token::Value token_;
-};
-
-
-class HCompareObjectEqAndBranch: public HTemplateControlInstruction<2, 2> {
- public:
- HCompareObjectEqAndBranch(HValue* left, HValue* right) {
- SetOperandAt(0, left);
- SetOperandAt(1, right);
- }
-
- HValue* left() { return OperandAt(0); }
- HValue* right() { return OperandAt(1); }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)
-};
-
-
-class HCompareConstantEqAndBranch: public HUnaryControlInstruction {
- public:
- HCompareConstantEqAndBranch(HValue* left, int right, Token::Value op)
- : HUnaryControlInstruction(left, NULL, NULL), op_(op), right_(right) {
- ASSERT(op == Token::EQ_STRICT);
- }
-
- Token::Value op() const { return op_; }
- HValue* left() { return value(); }
- int right() const { return right_; }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Integer32();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(CompareConstantEqAndBranch);
-
- private:
- const Token::Value op_;
- const int right_;
-};
-
-
-class HIsNilAndBranch: public HUnaryControlInstruction {
- public:
- HIsNilAndBranch(HValue* value, EqualityKind kind, NilValue nil)
- : HUnaryControlInstruction(value, NULL, NULL), kind_(kind), nil_(nil) { }
-
- EqualityKind kind() const { return kind_; }
- NilValue nil() const { return nil_; }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
- virtual Representation observed_input_representation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(IsNilAndBranch)
-
- private:
- EqualityKind kind_;
- NilValue nil_;
-};
-
-
-class HIsObjectAndBranch: public HUnaryControlInstruction {
- public:
- explicit HIsObjectAndBranch(HValue* value)
- : HUnaryControlInstruction(value, NULL, NULL) { }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch)
-};
-
-class HIsStringAndBranch: public HUnaryControlInstruction {
- public:
- explicit HIsStringAndBranch(HValue* value)
- : HUnaryControlInstruction(value, NULL, NULL) { }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
-};
-
-
-class HIsSmiAndBranch: public HUnaryControlInstruction {
- public:
- explicit HIsSmiAndBranch(HValue* value)
- : HUnaryControlInstruction(value, NULL, NULL) { }
-
- DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-};
-
-
-class HIsUndetectableAndBranch: public HUnaryControlInstruction {
- public:
- explicit HIsUndetectableAndBranch(HValue* value)
- : HUnaryControlInstruction(value, NULL, NULL) { }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)
-};
-
-
-class HStringCompareAndBranch: public HTemplateControlInstruction<2, 3> {
- public:
- HStringCompareAndBranch(HValue* context,
- HValue* left,
- HValue* right,
- Token::Value token)
- : token_(token) {
- ASSERT(Token::IsCompareOp(token));
- SetOperandAt(0, context);
- SetOperandAt(1, left);
- SetOperandAt(2, right);
- set_representation(Representation::Tagged());
- }
-
- HValue* context() { return OperandAt(0); }
- HValue* left() { return OperandAt(1); }
- HValue* right() { return OperandAt(2); }
- Token::Value token() const { return token_; }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- Representation GetInputRepresentation() const {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)
-
- private:
- Token::Value token_;
-};
-
-
-class HIsConstructCallAndBranch: public HTemplateControlInstruction<2, 0> {
- public:
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch)
-};
-
-
-class HHasInstanceTypeAndBranch: public HUnaryControlInstruction {
- public:
- 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) {
- ASSERT(to == LAST_TYPE); // Others not implemented yet in backend.
- }
-
- InstanceType from() { return from_; }
- InstanceType to() { return to_; }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
-
- private:
- InstanceType from_;
- InstanceType to_; // Inclusive range, not all combinations work.
-};
-
-
-class HHasCachedArrayIndexAndBranch: public HUnaryControlInstruction {
- public:
- explicit HHasCachedArrayIndexAndBranch(HValue* value)
- : HUnaryControlInstruction(value, NULL, NULL) { }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch)
-};
-
-
-class HGetCachedArrayIndex: public HUnaryOperation {
- public:
- explicit HGetCachedArrayIndex(HValue* value) : HUnaryOperation(value) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
-class HClassOfTestAndBranch: public HUnaryControlInstruction {
- public:
- HClassOfTestAndBranch(HValue* value, Handle<String> class_name)
- : HUnaryControlInstruction(value, NULL, NULL),
- class_name_(class_name) { }
-
- DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- Handle<String> class_name() const { return class_name_; }
-
- private:
- Handle<String> class_name_;
-};
-
-
-class HTypeofIsAndBranch: public HUnaryControlInstruction {
- public:
- HTypeofIsAndBranch(HValue* value, Handle<String> type_literal)
- : HUnaryControlInstruction(value, NULL, NULL),
- type_literal_(type_literal) { }
-
- Handle<String> type_literal() { return type_literal_; }
- virtual void PrintDataTo(StringStream* stream);
-
- DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- private:
- Handle<String> type_literal_;
-};
-
-
-class HInstanceOf: public HBinaryOperation {
- public:
- HInstanceOf(HValue* context, HValue* left, HValue* right)
- : HBinaryOperation(context, left, right) {
- set_representation(Representation::Tagged());
- SetAllSideEffects();
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- virtual HType CalculateInferredType();
-
- virtual void PrintDataTo(StringStream* stream);
-
- DECLARE_CONCRETE_INSTRUCTION(InstanceOf)
-};
-
-
-class HInstanceOfKnownGlobal: public HTemplateInstruction<2> {
- public:
- HInstanceOfKnownGlobal(HValue* context,
- HValue* left,
- Handle<JSFunction> right)
- : function_(right) {
- SetOperandAt(0, context);
- SetOperandAt(1, left);
- set_representation(Representation::Tagged());
- SetAllSideEffects();
- }
-
- HValue* context() { return OperandAt(0); }
- HValue* left() { return OperandAt(1); }
- Handle<JSFunction> function() { return function_; }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- virtual HType CalculateInferredType();
-
- DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal)
-
- private:
- Handle<JSFunction> function_;
-};
-
-
-// TODO(mstarzinger): This instruction should be modeled as a load of the map
-// field followed by a load of the instance size field once HLoadNamedField is
-// flexible enough to accommodate byte-field loads.
-class HInstanceSize: public HTemplateInstruction<1> {
- public:
- explicit HInstanceSize(HValue* object) {
- SetOperandAt(0, object);
- set_representation(Representation::Integer32());
- }
-
- HValue* object() { return OperandAt(0); }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(InstanceSize)
-};
-
-
-class HPower: public HTemplateInstruction<2> {
- public:
- static HInstruction* New(Zone* zone, HValue* left, HValue* right);
-
- HValue* left() { return OperandAt(0); }
- HValue* right() const { return OperandAt(1); }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return index == 0
- ? Representation::Double()
- : Representation::None();
- }
- virtual Representation observed_input_representation(int index) {
- return RequiredInputRepresentation(index);
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Power)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- private:
- HPower(HValue* left, HValue* right) {
- SetOperandAt(0, left);
- SetOperandAt(1, right);
- set_representation(Representation::Double());
- SetFlag(kUseGVN);
- SetGVNFlag(kChangesNewSpacePromotion);
- }
-
- virtual bool IsDeletable() const {
- return !right()->representation().IsTagged();
- }
-};
-
-
-class HRandom: public HTemplateInstruction<1> {
- public:
- explicit HRandom(HValue* global_object) {
- SetOperandAt(0, global_object);
- set_representation(Representation::Double());
- }
-
- HValue* global_object() { return OperandAt(0); }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Random)
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
-class HAdd: public HArithmeticBinaryOperation {
- public:
- static HInstruction* New(Zone* zone,
- HValue* context,
- HValue* left,
- HValue* right);
-
- // 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).
- virtual bool IsCommutative() const {
- return !representation().IsTagged();
- }
-
- virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
-
- virtual HType CalculateInferredType();
-
- virtual HValue* Canonicalize();
-
- virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* other) {
- HValue* base = NULL;
- int32_t offset = 0;
- if (left()->IsInteger32Constant()) {
- base = right();
- offset = left()->GetInteger32Constant();
- } else if (right()->IsInteger32Constant()) {
- base = left();
- offset = right()->GetInteger32Constant();
- } else {
- return false;
- }
-
- return relation.IsExtendable(offset)
- ? base->IsRelationTrue(relation, other) : false;
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Add)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- virtual Range* InferRange(Zone* zone);
-
- private:
- HAdd(HValue* context, HValue* left, HValue* right)
- : HArithmeticBinaryOperation(context, left, right) {
- SetFlag(kCanOverflow);
- }
-};
-
-
-class HSub: public HArithmeticBinaryOperation {
- public:
- static HInstruction* New(Zone* zone,
- HValue* context,
- HValue* left,
- HValue* right);
-
- virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
-
- virtual HValue* Canonicalize();
-
- virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* other) {
- if (right()->IsInteger32Constant()) {
- HValue* base = left();
- int32_t offset = right()->GetInteger32Constant();
- return relation.IsExtendable(-offset)
- ? base->IsRelationTrue(relation, other) : false;
- } else {
- return false;
- }
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Sub)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- virtual Range* InferRange(Zone* zone);
-
- private:
- HSub(HValue* context, HValue* left, HValue* right)
- : HArithmeticBinaryOperation(context, left, right) {
- SetFlag(kCanOverflow);
- }
-};
-
-
-class HMul: public HArithmeticBinaryOperation {
- public:
- static HInstruction* New(Zone* zone,
- HValue* context,
- HValue* left,
- HValue* right);
-
- virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
-
- // Only commutative if it is certain that not two objects are multiplicated.
- virtual bool IsCommutative() const {
- return !representation().IsTagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Mul)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- virtual Range* InferRange(Zone* zone);
-
- private:
- HMul(HValue* context, HValue* left, HValue* right)
- : HArithmeticBinaryOperation(context, left, right) {
- SetFlag(kCanOverflow);
- }
-};
-
-
-class HMod: public HArithmeticBinaryOperation {
- public:
- static HInstruction* New(Zone* zone,
- HValue* context,
- HValue* left,
- HValue* right);
-
- bool HasPowerOf2Divisor() {
- if (right()->IsConstant() &&
- HConstant::cast(right())->HasInteger32Value()) {
- int32_t value = HConstant::cast(right())->Integer32Value();
- return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value));
- }
-
- return false;
- }
-
- virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
-
- DECLARE_CONCRETE_INSTRUCTION(Mod)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- virtual Range* InferRange(Zone* zone);
-
- private:
- HMod(HValue* context, HValue* left, HValue* right)
- : HArithmeticBinaryOperation(context, left, right) {
- SetFlag(kCanBeDivByZero);
- }
-};
-
-
-class HDiv: public HArithmeticBinaryOperation {
- public:
- static HInstruction* New(Zone* zone,
- HValue* context,
- HValue* left,
- HValue* right);
-
- bool HasPowerOf2Divisor() {
- if (right()->IsConstant() &&
- HConstant::cast(right())->HasInteger32Value()) {
- int32_t value = HConstant::cast(right())->Integer32Value();
- return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value));
- }
-
- return false;
- }
-
- virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
-
- DECLARE_CONCRETE_INSTRUCTION(Div)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- virtual Range* InferRange(Zone* zone);
-
- private:
- HDiv(HValue* context, HValue* left, HValue* right)
- : HArithmeticBinaryOperation(context, left, right) {
- SetFlag(kCanBeDivByZero);
- SetFlag(kCanOverflow);
- }
-};
-
-
-class HMathMinMax: public HArithmeticBinaryOperation {
- public:
- enum Operation { kMathMin, kMathMax };
-
- static HInstruction* New(Zone* zone,
- HValue* context,
- HValue* left,
- HValue* right,
- Operation op);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return index == 0 ? Representation::Tagged()
- : representation();
- }
-
- virtual Representation observed_input_representation(int index) {
- return RequiredInputRepresentation(index);
- }
-
- virtual void InferRepresentation(HInferRepresentation* h_infer);
-
- virtual Representation RepresentationFromInputs() {
- Representation left_rep = left()->representation();
- Representation right_rep = right()->representation();
- if ((left_rep.IsNone() || left_rep.IsInteger32()) &&
- (right_rep.IsNone() || right_rep.IsInteger32())) {
- return Representation::Integer32();
- }
- return Representation::Double();
- }
-
- virtual bool IsCommutative() const { return true; }
-
- Operation operation() { return operation_; }
-
- DECLARE_CONCRETE_INSTRUCTION(MathMinMax)
-
- protected:
- virtual bool DataEquals(HValue* other) {
- return other->IsMathMinMax() &&
- HMathMinMax::cast(other)->operation_ == operation_;
- }
-
- virtual Range* InferRange(Zone* zone);
-
- private:
- HMathMinMax(HValue* context, HValue* left, HValue* right, Operation op)
- : HArithmeticBinaryOperation(context, left, right),
- operation_(op) { }
-
- Operation operation_;
-};
-
-
-class HBitwise: public HBitwiseBinaryOperation {
- public:
- static HInstruction* New(Zone* zone,
- Token::Value op,
- HValue* context,
- HValue* left,
- HValue* right);
-
- Token::Value op() const { return op_; }
-
- virtual bool IsCommutative() const { return true; }
-
- virtual HValue* Canonicalize();
-
- virtual void PrintDataTo(StringStream* stream);
-
- DECLARE_CONCRETE_INSTRUCTION(Bitwise)
-
- protected:
- virtual bool DataEquals(HValue* other) {
- return op() == HBitwise::cast(other)->op();
- }
-
- virtual Range* InferRange(Zone* zone);
-
- private:
- HBitwise(Token::Value op, HValue* context, HValue* left, HValue* right)
- : HBitwiseBinaryOperation(context, left, right), op_(op) {
- ASSERT(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR);
- }
-
- Token::Value op_;
-};
-
-
-class HShl: public HBitwiseBinaryOperation {
- public:
- static HInstruction* New(Zone* zone,
- HValue* context,
- HValue* left,
- HValue* right);
-
- virtual Range* InferRange(Zone* zone);
-
- DECLARE_CONCRETE_INSTRUCTION(Shl)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- private:
- HShl(HValue* context, HValue* left, HValue* right)
- : HBitwiseBinaryOperation(context, left, right) { }
-};
-
-
-class HShr: public HBitwiseBinaryOperation {
- public:
- static HInstruction* New(Zone* zone,
- HValue* context,
- HValue* left,
- HValue* right);
-
- virtual Range* InferRange(Zone* zone);
-
- DECLARE_CONCRETE_INSTRUCTION(Shr)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- private:
- HShr(HValue* context, HValue* left, HValue* right)
- : HBitwiseBinaryOperation(context, left, right) { }
-};
-
-
-class HSar: public HBitwiseBinaryOperation {
- public:
- static HInstruction* New(Zone* zone,
- HValue* context,
- HValue* left,
- HValue* right);
-
- virtual Range* InferRange(Zone* zone);
-
- DECLARE_CONCRETE_INSTRUCTION(Sar)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- private:
- HSar(HValue* context, HValue* left, HValue* right)
- : HBitwiseBinaryOperation(context, left, right) { }
-};
-
-
-class HRor: public HBitwiseBinaryOperation {
- public:
- HRor(HValue* context, HValue* left, HValue* right)
- : HBitwiseBinaryOperation(context, left, right) {
- ChangeRepresentation(Representation::Integer32());
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Ror)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-};
-
-
-class HOsrEntry: public HTemplateInstruction<0> {
- public:
- explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
- SetGVNFlag(kChangesOsrEntries);
- }
-
- BailoutId ast_id() const { return ast_id_; }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(OsrEntry)
-
- private:
- BailoutId ast_id_;
-};
-
-
-class HParameter: public HTemplateInstruction<0> {
- public:
- enum ParameterKind {
- STACK_PARAMETER,
- REGISTER_PARAMETER
- };
-
- explicit HParameter(unsigned index,
- ParameterKind kind = STACK_PARAMETER)
- : index_(index),
- kind_(kind) {
- set_representation(Representation::Tagged());
- }
-
- unsigned index() const { return index_; }
- ParameterKind kind() const { return kind_; }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Parameter)
-
- private:
- unsigned index_;
- ParameterKind kind_;
-};
-
-
-class HCallStub: public HUnaryCall {
- public:
- HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
- : HUnaryCall(context, argument_count),
- major_key_(major_key),
- transcendental_type_(TranscendentalCache::kNumberOfCaches) {
- }
-
- CodeStub::Major major_key() { return major_key_; }
-
- HValue* context() { return value(); }
-
- void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
- transcendental_type_ = transcendental_type;
- }
- TranscendentalCache::Type transcendental_type() {
- return transcendental_type_;
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(CallStub)
-
- private:
- CodeStub::Major major_key_;
- TranscendentalCache::Type transcendental_type_;
-};
-
-
-class HUnknownOSRValue: public HTemplateInstruction<0> {
- public:
- HUnknownOSRValue()
- : incoming_value_(NULL) {
- set_representation(Representation::Tagged());
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- void set_incoming_value(HPhi* value) {
- incoming_value_ = value;
- }
-
- HPhi* incoming_value() {
- return incoming_value_;
- }
-
- DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
-
- private:
- HPhi* incoming_value_;
-};
-
-
-class HLoadGlobalCell: public HTemplateInstruction<0> {
- public:
- HLoadGlobalCell(Handle<JSGlobalPropertyCell> cell, PropertyDetails details)
- : cell_(cell), details_(details) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnGlobalVars);
- }
-
- Handle<JSGlobalPropertyCell> cell() const { return cell_; }
- bool RequiresHoleCheck() const;
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual intptr_t Hashcode() {
- ASSERT_ALLOCATION_DISABLED;
- // Dereferencing to use the object's raw address for hashing is safe.
- AllowHandleDereference allow_handle_deref(isolate());
- return reinterpret_cast<intptr_t>(*cell_);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell)
-
- protected:
- virtual bool DataEquals(HValue* other) {
- HLoadGlobalCell* b = HLoadGlobalCell::cast(other);
- return cell_.is_identical_to(b->cell());
- }
-
- private:
- virtual bool IsDeletable() const { return !RequiresHoleCheck(); }
-
- Handle<JSGlobalPropertyCell> cell_;
- PropertyDetails details_;
-};
-
-
-class HLoadGlobalGeneric: public HTemplateInstruction<2> {
- public:
- HLoadGlobalGeneric(HValue* context,
- HValue* global_object,
- Handle<Object> name,
- bool for_typeof)
- : name_(name),
- for_typeof_(for_typeof) {
- SetOperandAt(0, context);
- SetOperandAt(1, global_object);
- set_representation(Representation::Tagged());
- SetAllSideEffects();
- }
-
- HValue* context() { return OperandAt(0); }
- HValue* global_object() { return OperandAt(1); }
- Handle<Object> name() const { return name_; }
- bool for_typeof() const { return for_typeof_; }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric)
-
- private:
- Handle<Object> name_;
- bool for_typeof_;
-};
-
-
-class HAllocateObject: public HTemplateInstruction<1> {
- public:
- HAllocateObject(HValue* context, Handle<JSFunction> constructor)
- : constructor_(constructor) {
- SetOperandAt(0, context);
- set_representation(Representation::Tagged());
- SetGVNFlag(kChangesNewSpacePromotion);
- }
-
- // Maximum instance size for which allocations will be inlined.
- static const int kMaxSize = 64 * kPointerSize;
-
- HValue* context() { return OperandAt(0); }
- Handle<JSFunction> constructor() { return constructor_; }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
- virtual Handle<Map> GetMonomorphicJSObjectMap() {
- ASSERT(constructor()->has_initial_map());
- return Handle<Map>(constructor()->initial_map());
- }
- virtual HType CalculateInferredType();
-
- DECLARE_CONCRETE_INSTRUCTION(AllocateObject)
-
- private:
- // TODO(svenpanne) Might be safe, but leave it out until we know for sure.
- // virtual bool IsDeletable() const { return true; }
-
- Handle<JSFunction> constructor_;
-};
-
-
-class HAllocate: public HTemplateInstruction<2> {
- public:
- enum Flags {
- CAN_ALLOCATE_IN_NEW_SPACE = 1 << 0,
- CAN_ALLOCATE_IN_OLD_DATA_SPACE = 1 << 1,
- CAN_ALLOCATE_IN_OLD_POINTER_SPACE = 1 << 2,
- ALLOCATE_DOUBLE_ALIGNED = 1 << 3
- };
-
- HAllocate(HValue* context, HValue* size, HType type, Flags flags)
- : type_(type),
- flags_(flags) {
- ASSERT((flags & CAN_ALLOCATE_IN_OLD_DATA_SPACE) == 0); // unimplemented
- ASSERT((flags & CAN_ALLOCATE_IN_OLD_POINTER_SPACE) == 0); // unimplemented
- SetOperandAt(0, context);
- SetOperandAt(1, size);
- set_representation(Representation::Tagged());
- SetGVNFlag(kChangesNewSpacePromotion);
- }
-
- HValue* context() { return OperandAt(0); }
- HValue* size() { return OperandAt(1); }
-
- virtual Representation RequiredInputRepresentation(int index) {
- if (index == 0) {
- return Representation::Tagged();
- } else {
- return Representation::Integer32();
- }
- }
-
- virtual HType CalculateInferredType();
-
- bool CanAllocateInNewSpace() const {
- return (flags_ & CAN_ALLOCATE_IN_NEW_SPACE) != 0;
- }
-
- bool CanAllocateInOldDataSpace() const {
- return (flags_ & CAN_ALLOCATE_IN_OLD_DATA_SPACE) != 0;
- }
-
- bool CanAllocateInOldPointerSpace() const {
- return (flags_ & CAN_ALLOCATE_IN_OLD_POINTER_SPACE) != 0;
- }
-
- bool CanAllocateInOldSpace() const {
- return CanAllocateInOldDataSpace() ||
- CanAllocateInOldPointerSpace();
- }
-
- bool GuaranteedInNewSpace() const {
- return CanAllocateInNewSpace() && !CanAllocateInOldSpace();
- }
-
- bool MustAllocateDoubleAligned() const {
- return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0;
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Allocate)
-
- private:
- HType type_;
- Flags flags_;
-};
-
-
-inline bool StoringValueNeedsWriteBarrier(HValue* value) {
- return !value->type().IsBoolean()
- && !value->type().IsSmi()
- && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable());
-}
-
-
-inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
- HValue* new_space_dominator) {
- if (object != new_space_dominator) return true;
- if (object->IsFastLiteral()) return false;
- if (object->IsAllocateObject()) return false;
- if (object->IsAllocate()) {
- return !HAllocate::cast(object)->GuaranteedInNewSpace();
- }
- return true;
-}
-
-
-class HStoreGlobalCell: public HUnaryOperation {
- public:
- HStoreGlobalCell(HValue* value,
- Handle<JSGlobalPropertyCell> cell,
- PropertyDetails details)
- : HUnaryOperation(value),
- cell_(cell),
- details_(details) {
- SetGVNFlag(kChangesGlobalVars);
- }
-
- Handle<JSGlobalPropertyCell> cell() const { return cell_; }
- bool RequiresHoleCheck() {
- return !details_.IsDontDelete() || details_.IsReadOnly();
- }
- bool NeedsWriteBarrier() {
- return StoringValueNeedsWriteBarrier(value());
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
- virtual void PrintDataTo(StringStream* stream);
-
- DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell)
-
- private:
- Handle<JSGlobalPropertyCell> cell_;
- PropertyDetails details_;
-};
-
-
-class HStoreGlobalGeneric: public HTemplateInstruction<3> {
- public:
- HStoreGlobalGeneric(HValue* context,
- HValue* global_object,
- Handle<Object> name,
- HValue* value,
- StrictModeFlag strict_mode_flag)
- : name_(name),
- strict_mode_flag_(strict_mode_flag) {
- SetOperandAt(0, context);
- SetOperandAt(1, global_object);
- SetOperandAt(2, value);
- set_representation(Representation::Tagged());
- SetAllSideEffects();
- }
-
- HValue* context() { return OperandAt(0); }
- HValue* global_object() { return OperandAt(1); }
- Handle<Object> name() const { return name_; }
- HValue* value() { return OperandAt(2); }
- StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric)
-
- private:
- Handle<Object> name_;
- StrictModeFlag strict_mode_flag_;
-};
-
-
-class HLoadContextSlot: 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, Variable* var)
- : HUnaryOperation(context), slot_index_(var->index()) {
- ASSERT(var->IsContextSlot());
- switch (var->mode()) {
- case LET:
- case CONST_HARMONY:
- mode_ = kCheckDeoptimize;
- break;
- case CONST:
- mode_ = kCheckReturnUndefined;
- break;
- default:
- mode_ = kNoCheck;
- }
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnContextSlots);
- }
-
- int slot_index() const { return slot_index_; }
- Mode mode() const { return mode_; }
-
- bool DeoptimizesOnHole() {
- return mode_ == kCheckDeoptimize;
- }
-
- bool RequiresHoleCheck() const {
- return mode_ != kNoCheck;
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)
-
- protected:
- virtual bool DataEquals(HValue* other) {
- HLoadContextSlot* b = HLoadContextSlot::cast(other);
- return (slot_index() == b->slot_index());
- }
-
- private:
- virtual bool IsDeletable() const { return !RequiresHoleCheck(); }
-
- int slot_index_;
- Mode mode_;
-};
-
-
-class HStoreContextSlot: 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
- };
-
- HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
- : slot_index_(slot_index), mode_(mode) {
- SetOperandAt(0, context);
- SetOperandAt(1, value);
- SetGVNFlag(kChangesContextSlots);
- }
-
- HValue* context() { return OperandAt(0); }
- HValue* value() { 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;
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
-
- private:
- int slot_index_;
- Mode mode_;
-};
-
-
-class HLoadNamedField: public HUnaryOperation {
- public:
- HLoadNamedField(HValue* object, bool is_in_object, int offset)
- : HUnaryOperation(object),
- is_in_object_(is_in_object),
- offset_(offset) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnMaps);
- if (is_in_object) {
- SetGVNFlag(kDependsOnInobjectFields);
- } else {
- SetGVNFlag(kDependsOnBackingStoreFields);
- }
- }
-
- HValue* object() { return OperandAt(0); }
- bool is_in_object() const { return is_in_object_; }
- int offset() const { return offset_; }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
- virtual void PrintDataTo(StringStream* stream);
-
- DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
-
- protected:
- virtual bool DataEquals(HValue* other) {
- HLoadNamedField* b = HLoadNamedField::cast(other);
- return is_in_object_ == b->is_in_object_ && offset_ == b->offset_;
- }
-
- private:
- virtual bool IsDeletable() const { return true; }
-
- bool is_in_object_;
- int offset_;
-};
-
-
-class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> {
- public:
- HLoadNamedFieldPolymorphic(HValue* context,
- HValue* object,
- SmallMapList* types,
- Handle<String> name,
- Zone* zone);
-
- HValue* context() { return OperandAt(0); }
- HValue* object() { return OperandAt(1); }
- SmallMapList* types() { return &types_; }
- Handle<String> name() { return name_; }
- bool need_generic() { return need_generic_; }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- DECLARE_CONCRETE_INSTRUCTION(LoadNamedFieldPolymorphic)
-
- static const int kMaxLoadPolymorphism = 4;
-
- protected:
- virtual bool DataEquals(HValue* value);
-
- private:
- SmallMapList types_;
- Handle<String> name_;
- bool need_generic_;
-};
-
-
-
-class HLoadNamedGeneric: public HTemplateInstruction<2> {
- public:
- HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name)
- : name_(name) {
- SetOperandAt(0, context);
- SetOperandAt(1, object);
- set_representation(Representation::Tagged());
- SetAllSideEffects();
- }
-
- HValue* context() { return OperandAt(0); }
- HValue* object() { return OperandAt(1); }
- Handle<Object> name() const { return name_; }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
-
- private:
- Handle<Object> name_;
-};
-
-
-class HLoadFunctionPrototype: public HUnaryOperation {
- public:
- explicit HLoadFunctionPrototype(HValue* function)
- : HUnaryOperation(function) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnCalls);
- }
-
- HValue* function() { return OperandAt(0); }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-};
-
-class ArrayInstructionInterface {
- public:
- virtual HValue* GetKey() = 0;
- virtual void SetKey(HValue* key) = 0;
- virtual void SetIndexOffset(uint32_t index_offset) = 0;
- virtual bool IsDehoisted() = 0;
- virtual void SetDehoisted(bool is_dehoisted) = 0;
- virtual ~ArrayInstructionInterface() { };
-
- static Representation KeyedAccessIndexRequirement(Representation r) {
- return r.IsInteger32() ? Representation::Integer32()
- : Representation::Tagged();
- }
-};
-
-
-enum LoadKeyedHoleMode {
- NEVER_RETURN_HOLE,
- ALLOW_RETURN_HOLE
-};
-
-
-class HLoadKeyed
- : public HTemplateInstruction<3>, public ArrayInstructionInterface {
- public:
- HLoadKeyed(HValue* obj,
- HValue* key,
- HValue* dependency,
- ElementsKind elements_kind,
- LoadKeyedHoleMode mode = NEVER_RETURN_HOLE)
- : bit_field_(0) {
- bit_field_ = ElementsKindField::encode(elements_kind) |
- HoleModeField::encode(mode);
-
- SetOperandAt(0, obj);
- SetOperandAt(1, key);
- SetOperandAt(2, dependency != NULL ? dependency : obj);
-
- if (!is_external()) {
- // I can detect the case between storing double (holey and fast) and
- // smi/object by looking at elements_kind_.
- ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) ||
- IsFastDoubleElementsKind(elements_kind));
-
- if (IsFastSmiOrObjectElementsKind(elements_kind)) {
- if (IsFastSmiElementsKind(elements_kind)) {
- set_type(HType::Smi());
- }
-
- set_representation(Representation::Tagged());
- SetGVNFlag(kDependsOnArrayElements);
- } else {
- set_representation(Representation::Double());
- SetGVNFlag(kDependsOnDoubleArrayElements);
- }
- } else {
- if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
- elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
- set_representation(Representation::Double());
- } else {
- set_representation(Representation::Integer32());
- }
-
- SetGVNFlag(kDependsOnSpecializedArrayElements);
- // Native code could change the specialized array.
- SetGVNFlag(kDependsOnCalls);
- }
-
- SetFlag(kUseGVN);
- }
-
- bool is_external() const {
- return IsExternalArrayElementsKind(elements_kind());
- }
- HValue* elements() { return OperandAt(0); }
- HValue* key() { return OperandAt(1); }
- HValue* dependency() {
- ASSERT(HasDependency());
- return OperandAt(2);
- }
- bool HasDependency() const { return OperandAt(0) != OperandAt(2); }
- uint32_t index_offset() { return IndexOffsetField::decode(bit_field_); }
- void SetIndexOffset(uint32_t index_offset) {
- bit_field_ = IndexOffsetField::update(bit_field_, index_offset);
- }
- HValue* GetKey() { return key(); }
- void SetKey(HValue* key) { SetOperandAt(1, key); }
- bool IsDehoisted() { return IsDehoistedField::decode(bit_field_); }
- void SetDehoisted(bool is_dehoisted) {
- bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
- }
- ElementsKind elements_kind() const {
- return ElementsKindField::decode(bit_field_);
- }
- LoadKeyedHoleMode hole_mode() const {
- return HoleModeField::decode(bit_field_);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- // kind_fast: tagged[int32] (none)
- // kind_double: tagged[int32] (none)
- // kind_external: external[int32] (none)
- if (index == 0) {
- return is_external() ? Representation::External()
- : Representation::Tagged();
- }
- if (index == 1) {
- return ArrayInstructionInterface::KeyedAccessIndexRequirement(
- OperandAt(1)->representation());
- }
- return Representation::None();
- }
-
- virtual Representation observed_input_representation(int index) {
- return RequiredInputRepresentation(index);
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- bool UsesMustHandleHole() const;
- bool RequiresHoleCheck() const;
-
- virtual Range* InferRange(Zone* zone);
-
- DECLARE_CONCRETE_INSTRUCTION(LoadKeyed)
-
- protected:
- virtual bool DataEquals(HValue* other) {
- if (!other->IsLoadKeyed()) return false;
- HLoadKeyed* other_load = HLoadKeyed::cast(other);
-
- if (IsDehoisted() && index_offset() != other_load->index_offset())
- return false;
- return elements_kind() == other_load->elements_kind();
- }
-
- private:
- virtual bool IsDeletable() const {
- return !RequiresHoleCheck();
- }
-
- // Establish some checks around our packed fields
- enum LoadKeyedBits {
- kBitsForElementsKind = 5,
- kBitsForHoleMode = 1,
- kBitsForIndexOffset = 25,
- kBitsForIsDehoisted = 1,
-
- kStartElementsKind = 0,
- kStartHoleMode = kStartElementsKind + kBitsForElementsKind,
- kStartIndexOffset = kStartHoleMode + kBitsForHoleMode,
- kStartIsDehoisted = kStartIndexOffset + kBitsForIndexOffset
- };
-
- STATIC_ASSERT((kBitsForElementsKind + kBitsForIndexOffset +
- 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 IndexOffsetField:
- public BitField<uint32_t, kStartIndexOffset, kBitsForIndexOffset>
- {}; // NOLINT
- class IsDehoistedField:
- public BitField<bool, kStartIsDehoisted, kBitsForIsDehoisted>
- {}; // NOLINT
- uint32_t bit_field_;
-};
-
-
-class HLoadKeyedGeneric: public HTemplateInstruction<3> {
- public:
- HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key) {
- set_representation(Representation::Tagged());
- SetOperandAt(0, obj);
- SetOperandAt(1, key);
- SetOperandAt(2, context);
- SetAllSideEffects();
- }
-
- HValue* object() { return OperandAt(0); }
- HValue* key() { return OperandAt(1); }
- HValue* context() { return OperandAt(2); }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual Representation RequiredInputRepresentation(int index) {
- // tagged[tagged]
- return Representation::Tagged();
- }
-
- virtual HValue* Canonicalize();
-
- DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric)
-};
-
-
-class HStoreNamedField: public HTemplateInstruction<2> {
- public:
- HStoreNamedField(HValue* obj,
- Handle<String> name,
- HValue* val,
- bool in_object,
- int offset)
- : name_(name),
- is_in_object_(in_object),
- offset_(offset),
- new_space_dominator_(NULL) {
- SetOperandAt(0, obj);
- SetOperandAt(1, val);
- SetFlag(kTrackSideEffectDominators);
- SetGVNFlag(kDependsOnNewSpacePromotion);
- if (is_in_object_) {
- SetGVNFlag(kChangesInobjectFields);
- } else {
- SetGVNFlag(kChangesBackingStoreFields);
- }
- }
-
- DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
- virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) {
- ASSERT(side_effect == kChangesNewSpacePromotion);
- new_space_dominator_ = dominator;
- }
- virtual void PrintDataTo(StringStream* stream);
-
- HValue* object() { return OperandAt(0); }
- HValue* value() { return OperandAt(1); }
-
- Handle<String> name() const { return name_; }
- bool is_in_object() const { return is_in_object_; }
- int offset() const { return offset_; }
- Handle<Map> transition() const { return transition_; }
- void set_transition(Handle<Map> map) { transition_ = map; }
- HValue* new_space_dominator() const { return new_space_dominator_; }
-
- bool NeedsWriteBarrier() {
- return StoringValueNeedsWriteBarrier(value()) &&
- ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
- }
-
- bool NeedsWriteBarrierForMap() {
- return ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
- }
-
- private:
- Handle<String> name_;
- bool is_in_object_;
- int offset_;
- Handle<Map> transition_;
- HValue* new_space_dominator_;
-};
-
-
-class HStoreNamedGeneric: public HTemplateInstruction<3> {
- public:
- HStoreNamedGeneric(HValue* context,
- HValue* object,
- Handle<String> name,
- HValue* value,
- StrictModeFlag strict_mode_flag)
- : name_(name),
- strict_mode_flag_(strict_mode_flag) {
- SetOperandAt(0, object);
- SetOperandAt(1, value);
- SetOperandAt(2, context);
- SetAllSideEffects();
- }
-
- HValue* object() { return OperandAt(0); }
- HValue* value() { return OperandAt(1); }
- HValue* context() { return OperandAt(2); }
- Handle<String> name() { return name_; }
- StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric)
-
- private:
- Handle<String> name_;
- StrictModeFlag strict_mode_flag_;
-};
-
-
-class HStoreKeyed
- : public HTemplateInstruction<3>, public ArrayInstructionInterface {
- public:
- HStoreKeyed(HValue* obj, HValue* key, HValue* val,
- ElementsKind elements_kind)
- : elements_kind_(elements_kind),
- index_offset_(0),
- is_dehoisted_(false),
- new_space_dominator_(NULL) {
- SetOperandAt(0, obj);
- SetOperandAt(1, key);
- SetOperandAt(2, val);
-
- if (IsFastObjectElementsKind(elements_kind)) {
- SetFlag(kTrackSideEffectDominators);
- SetGVNFlag(kDependsOnNewSpacePromotion);
- }
- if (is_external()) {
- SetGVNFlag(kChangesSpecializedArrayElements);
- } else if (IsFastDoubleElementsKind(elements_kind)) {
- SetGVNFlag(kChangesDoubleArrayElements);
- SetFlag(kDeoptimizeOnUndefined);
- } else {
- SetGVNFlag(kChangesArrayElements);
- }
-
- // EXTERNAL_{UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
- if (elements_kind >= EXTERNAL_BYTE_ELEMENTS &&
- elements_kind <= EXTERNAL_UNSIGNED_INT_ELEMENTS) {
- SetFlag(kTruncatingToInt32);
- }
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- // kind_fast: tagged[int32] = tagged
- // kind_double: tagged[int32] = double
- // kind_external: external[int32] = (double | int32)
- if (index == 0) {
- return is_external() ? Representation::External()
- : Representation::Tagged();
- } else if (index == 1) {
- return ArrayInstructionInterface::KeyedAccessIndexRequirement(
- OperandAt(1)->representation());
- }
-
- ASSERT_EQ(index, 2);
- if (IsDoubleOrFloatElementsKind(elements_kind())) {
- return Representation::Double();
- }
-
- return is_external() ? Representation::Integer32()
- : Representation::Tagged();
- }
-
- bool is_external() const {
- return IsExternalArrayElementsKind(elements_kind());
- }
-
- virtual Representation observed_input_representation(int index) {
- if (index < 2) return RequiredInputRepresentation(index);
- if (IsDoubleOrFloatElementsKind(elements_kind())) {
- return Representation::Double();
- }
- if (is_external()) {
- return Representation::Integer32();
- }
- // For fast object elements kinds, don't assume anything.
- return Representation::None();
- }
-
- HValue* elements() { return OperandAt(0); }
- HValue* key() { return OperandAt(1); }
- HValue* value() { return OperandAt(2); }
- bool value_is_smi() const {
- return IsFastSmiElementsKind(elements_kind_);
- }
- ElementsKind elements_kind() const { return elements_kind_; }
- uint32_t index_offset() { return index_offset_; }
- void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
- HValue* GetKey() { return key(); }
- void SetKey(HValue* key) { SetOperandAt(1, key); }
- bool IsDehoisted() { return is_dehoisted_; }
- void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
-
- virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) {
- ASSERT(side_effect == kChangesNewSpacePromotion);
- new_space_dominator_ = dominator;
- }
-
- HValue* new_space_dominator() const { return new_space_dominator_; }
-
- bool NeedsWriteBarrier() {
- if (value_is_smi()) {
- return false;
- } else {
- return StoringValueNeedsWriteBarrier(value()) &&
- ReceiverObjectNeedsWriteBarrier(elements(), new_space_dominator());
- }
- }
-
- bool NeedsCanonicalization();
-
- virtual void PrintDataTo(StringStream* stream);
-
- DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)
-
- private:
- ElementsKind elements_kind_;
- uint32_t index_offset_;
- bool is_dehoisted_;
- HValue* new_space_dominator_;
-};
-
-
-class HStoreKeyedGeneric: public HTemplateInstruction<4> {
- public:
- HStoreKeyedGeneric(HValue* context,
- HValue* object,
- HValue* key,
- HValue* value,
- StrictModeFlag strict_mode_flag)
- : strict_mode_flag_(strict_mode_flag) {
- SetOperandAt(0, object);
- SetOperandAt(1, key);
- SetOperandAt(2, value);
- SetOperandAt(3, context);
- SetAllSideEffects();
- }
-
- HValue* object() { return OperandAt(0); }
- HValue* key() { return OperandAt(1); }
- HValue* value() { return OperandAt(2); }
- HValue* context() { return OperandAt(3); }
- StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
-
- virtual Representation RequiredInputRepresentation(int index) {
- // tagged[tagged] = tagged
- return Representation::Tagged();
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric)
-
- private:
- StrictModeFlag strict_mode_flag_;
-};
-
-
-class HTransitionElementsKind: public HTemplateInstruction<2> {
- public:
- HTransitionElementsKind(HValue* context,
- HValue* object,
- Handle<Map> original_map,
- Handle<Map> transitioned_map)
- : original_map_(original_map),
- transitioned_map_(transitioned_map),
- from_kind_(original_map->elements_kind()),
- to_kind_(transitioned_map->elements_kind()) {
- SetOperandAt(0, object);
- SetOperandAt(1, context);
- SetFlag(kUseGVN);
- SetGVNFlag(kChangesElementsKind);
- if (original_map->has_fast_double_elements()) {
- SetGVNFlag(kChangesElementsPointer);
- SetGVNFlag(kChangesNewSpacePromotion);
- }
- if (transitioned_map->has_fast_double_elements()) {
- SetGVNFlag(kChangesElementsPointer);
- SetGVNFlag(kChangesNewSpacePromotion);
- }
- set_representation(Representation::Tagged());
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- HValue* object() { return OperandAt(0); }
- HValue* context() { return OperandAt(1); }
- Handle<Map> original_map() { return original_map_; }
- Handle<Map> transitioned_map() { return transitioned_map_; }
- ElementsKind from_kind() { return from_kind_; }
- ElementsKind to_kind() { return to_kind_; }
-
- virtual void PrintDataTo(StringStream* stream);
-
- DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
-
- protected:
- virtual bool DataEquals(HValue* other) {
- HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
- return original_map_.is_identical_to(instr->original_map()) &&
- transitioned_map_.is_identical_to(instr->transitioned_map());
- }
-
- private:
- Handle<Map> original_map_;
- Handle<Map> transitioned_map_;
- ElementsKind from_kind_;
- ElementsKind to_kind_;
-};
-
-
-class HStringAdd: public HBinaryOperation {
- public:
- static HInstruction* New(Zone* zone,
- HValue* context,
- HValue* left,
- HValue* right);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- virtual HType CalculateInferredType() {
- return HType::String();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(StringAdd)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
-
- private:
- HStringAdd(HValue* context, HValue* left, HValue* right)
- : HBinaryOperation(context, left, right) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnMaps);
- SetGVNFlag(kChangesNewSpacePromotion);
- }
-
- // TODO(svenpanne) Might be safe, but leave it out until we know for sure.
- // virtual bool IsDeletable() const { return true; }
-};
-
-
-class HStringCharCodeAt: public HTemplateInstruction<3> {
- public:
- HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
- SetOperandAt(0, context);
- SetOperandAt(1, string);
- SetOperandAt(2, index);
- set_representation(Representation::Integer32());
- SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnMaps);
- SetGVNFlag(kChangesNewSpacePromotion);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- // The index is supposed to be Integer32.
- return index == 2
- ? Representation::Integer32()
- : Representation::Tagged();
- }
-
- HValue* context() { return OperandAt(0); }
- HValue* string() { return OperandAt(1); }
- HValue* index() { return OperandAt(2); }
-
- DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- virtual Range* InferRange(Zone* zone) {
- return new(zone) Range(0, String::kMaxUtf16CodeUnit);
- }
-
- // TODO(svenpanne) Might be safe, but leave it out until we know for sure.
- // private:
- // virtual bool IsDeletable() const { return true; }
-};
-
-
-class HStringCharFromCode: public HTemplateInstruction<2> {
- public:
- static HInstruction* New(Zone* zone,
- HValue* context,
- HValue* char_code);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return index == 0
- ? Representation::Tagged()
- : Representation::Integer32();
- }
- virtual HType CalculateInferredType();
-
- HValue* context() { return OperandAt(0); }
- HValue* value() { return OperandAt(1); }
-
- virtual bool DataEquals(HValue* other) { return true; }
-
- DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
-
- private:
- HStringCharFromCode(HValue* context, HValue* char_code) {
- SetOperandAt(0, context);
- SetOperandAt(1, char_code);
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetGVNFlag(kChangesNewSpacePromotion);
- }
-
- // TODO(svenpanne) Might be safe, but leave it out until we know for sure.
- // virtual bool IsDeletable() const { return true; }
-};
-
-
-class HStringLength: public HUnaryOperation {
- public:
- static HInstruction* New(Zone* zone, HValue* string);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- virtual HType CalculateInferredType() {
- STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
- return HType::Smi();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(StringLength)
-
- protected:
- virtual bool DataEquals(HValue* other) { return true; }
-
- virtual Range* InferRange(Zone* zone) {
- return new(zone) Range(0, String::kMaxLength);
- }
-
- private:
- explicit HStringLength(HValue* string) : HUnaryOperation(string) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnMaps);
- }
-
- virtual bool IsDeletable() const { return true; }
-};
-
-
-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:
- virtual bool IsDeletable() const { return true; }
-
- int literal_index_;
- int depth_;
- AllocationSiteMode allocation_site_mode_;
-};
-
-
-class HFastLiteral: public HMaterializedLiteral<1> {
- public:
- HFastLiteral(HValue* context,
- Handle<JSObject> boilerplate,
- int total_size,
- int literal_index,
- int depth,
- AllocationSiteMode mode)
- : HMaterializedLiteral<1>(literal_index, depth, mode),
- boilerplate_(boilerplate),
- total_size_(total_size) {
- SetOperandAt(0, context);
- SetGVNFlag(kChangesNewSpacePromotion);
- }
-
- // Maximum depth and total number of elements and properties for literal
- // graphs to be considered for fast deep-copying.
- static const int kMaxLiteralDepth = 3;
- static const int kMaxLiteralProperties = 8;
-
- HValue* context() { return OperandAt(0); }
- Handle<JSObject> boilerplate() const { return boilerplate_; }
- int total_size() const { return total_size_; }
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
- virtual Handle<Map> GetMonomorphicJSObjectMap() {
- return Handle<Map>(boilerplate()->map());
- }
- virtual HType CalculateInferredType();
-
- DECLARE_CONCRETE_INSTRUCTION(FastLiteral)
-
- private:
- Handle<JSObject> boilerplate_;
- int total_size_;
-};
-
-
-class HArrayLiteral: public HMaterializedLiteral<1> {
- public:
- HArrayLiteral(HValue* context,
- Handle<HeapObject> boilerplate_object,
- int length,
- int literal_index,
- int depth,
- AllocationSiteMode mode)
- : HMaterializedLiteral<1>(literal_index, depth, mode),
- length_(length),
- boilerplate_object_(boilerplate_object) {
- SetOperandAt(0, context);
- SetGVNFlag(kChangesNewSpacePromotion);
- }
-
- HValue* context() { return OperandAt(0); }
- ElementsKind boilerplate_elements_kind() const {
- if (!boilerplate_object_->IsJSObject()) {
- return TERMINAL_FAST_ELEMENTS_KIND;
- }
- return Handle<JSObject>::cast(boilerplate_object_)->GetElementsKind();
- }
- Handle<HeapObject> boilerplate_object() const { return boilerplate_object_; }
- int length() const { return length_; }
- bool IsCopyOnWrite() const;
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
- virtual HType CalculateInferredType();
-
- DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral)
-
- private:
- int length_;
- Handle<HeapObject> boilerplate_object_;
-};
-
-
-class HObjectLiteral: public HMaterializedLiteral<1> {
- public:
- HObjectLiteral(HValue* context,
- Handle<FixedArray> constant_properties,
- bool fast_elements,
- int literal_index,
- int depth,
- bool has_function)
- : HMaterializedLiteral<1>(literal_index, depth),
- constant_properties_(constant_properties),
- fast_elements_(fast_elements),
- has_function_(has_function) {
- SetOperandAt(0, context);
- SetGVNFlag(kChangesNewSpacePromotion);
- }
-
- HValue* context() { return OperandAt(0); }
- Handle<FixedArray> constant_properties() const {
- return constant_properties_;
- }
- bool fast_elements() const { return fast_elements_; }
- bool has_function() const { return has_function_; }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
- virtual HType CalculateInferredType();
-
- DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral)
-
- private:
- Handle<FixedArray> constant_properties_;
- bool fast_elements_;
- bool has_function_;
-};
-
-
-class HRegExpLiteral: public HMaterializedLiteral<1> {
- public:
- 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();
- }
-
- HValue* context() { return OperandAt(0); }
- Handle<FixedArray> literals() { return literals_; }
- Handle<String> pattern() { return pattern_; }
- Handle<String> flags() { return flags_; }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
- virtual HType CalculateInferredType();
-
- DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral)
-
- private:
- Handle<FixedArray> literals_;
- Handle<String> pattern_;
- Handle<String> flags_;
-};
-
-
-class HFunctionLiteral: public HTemplateInstruction<1> {
- public:
- HFunctionLiteral(HValue* context,
- Handle<SharedFunctionInfo> shared,
- bool pretenure)
- : shared_info_(shared), pretenure_(pretenure) {
- SetOperandAt(0, context);
- set_representation(Representation::Tagged());
- SetGVNFlag(kChangesNewSpacePromotion);
- }
-
- HValue* context() { return OperandAt(0); }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
- virtual HType CalculateInferredType();
-
- DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral)
-
- Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
- bool pretenure() const { return pretenure_; }
-
- private:
- virtual bool IsDeletable() const { return true; }
-
- Handle<SharedFunctionInfo> shared_info_;
- bool pretenure_;
-};
-
-
-class HTypeof: public HTemplateInstruction<2> {
- public:
- explicit HTypeof(HValue* context, HValue* value) {
- SetOperandAt(0, context);
- SetOperandAt(1, value);
- set_representation(Representation::Tagged());
- }
-
- HValue* context() { return OperandAt(0); }
- HValue* value() { return OperandAt(1); }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Typeof)
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
-class HTrapAllocationMemento : public HTemplateInstruction<1> {
- public:
- explicit HTrapAllocationMemento(HValue* obj) {
- SetOperandAt(0, obj);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- HValue* object() { return OperandAt(0); }
-
- DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento)
-};
-
-
-class HToFastProperties: public HUnaryOperation {
- public:
- explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
- // This instruction is not marked as having side effects, but
- // changes the map of the input operand. Use it only when creating
- // object literals.
- ASSERT(value->IsObjectLiteral() || value->IsFastLiteral());
- set_representation(Representation::Tagged());
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(ToFastProperties)
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
-class HValueOf: public HUnaryOperation {
- public:
- explicit HValueOf(HValue* value) : HUnaryOperation(value) {
- set_representation(Representation::Tagged());
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(ValueOf)
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
-class HDateField: public HUnaryOperation {
- public:
- HDateField(HValue* date, Smi* index)
- : HUnaryOperation(date), index_(index) {
- set_representation(Representation::Tagged());
- }
-
- Smi* index() const { return index_; }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(DateField)
-
- private:
- Smi* index_;
-};
-
-
-class HSeqStringSetChar: public HTemplateInstruction<3> {
- public:
- HSeqStringSetChar(String::Encoding encoding,
- HValue* string,
- HValue* index,
- HValue* value) : encoding_(encoding) {
- SetOperandAt(0, string);
- SetOperandAt(1, index);
- SetOperandAt(2, value);
- }
-
- String::Encoding encoding() { return encoding_; }
- HValue* string() { return OperandAt(0); }
- HValue* index() { return OperandAt(1); }
- HValue* value() { return OperandAt(2); }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar)
-
- private:
- String::Encoding encoding_;
-};
-
-
-class HDeleteProperty: public HBinaryOperation {
- public:
- HDeleteProperty(HValue* context, HValue* obj, HValue* key)
- : HBinaryOperation(context, obj, key) {
- set_representation(Representation::Tagged());
- SetAllSideEffects();
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- virtual HType CalculateInferredType();
-
- DECLARE_CONCRETE_INSTRUCTION(DeleteProperty)
-
- HValue* object() { return left(); }
- HValue* key() { return right(); }
-};
-
-
-class HIn: public HTemplateInstruction<3> {
- public:
- HIn(HValue* context, HValue* key, HValue* object) {
- SetOperandAt(0, context);
- SetOperandAt(1, key);
- SetOperandAt(2, object);
- set_representation(Representation::Tagged());
- SetAllSideEffects();
- }
-
- HValue* context() { return OperandAt(0); }
- HValue* key() { return OperandAt(1); }
- HValue* object() { return OperandAt(2); }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- virtual HType CalculateInferredType() {
- return HType::Boolean();
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- DECLARE_CONCRETE_INSTRUCTION(In)
-};
-
-
-class HCheckMapValue: public HTemplateInstruction<2> {
- public:
- HCheckMapValue(HValue* value,
- HValue* map) {
- SetOperandAt(0, value);
- SetOperandAt(1, map);
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnMaps);
- SetGVNFlag(kDependsOnElementsKind);
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual HType CalculateInferredType() {
- return HType::Tagged();
- }
-
- HValue* value() { return OperandAt(0); }
- HValue* map() { return OperandAt(1); }
-
- DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
-
- protected:
- virtual bool DataEquals(HValue* other) {
- return true;
- }
-};
-
-
-class HForInPrepareMap : public HTemplateInstruction<2> {
- public:
- HForInPrepareMap(HValue* context,
- HValue* object) {
- SetOperandAt(0, context);
- SetOperandAt(1, object);
- set_representation(Representation::Tagged());
- SetAllSideEffects();
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- HValue* context() { return OperandAt(0); }
- HValue* enumerable() { return OperandAt(1); }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual HType CalculateInferredType() {
- return HType::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
-};
-
-
-class HForInCacheArray : public HTemplateInstruction<2> {
- public:
- HForInCacheArray(HValue* enumerable,
- HValue* keys,
- int idx) : idx_(idx) {
- SetOperandAt(0, enumerable);
- SetOperandAt(1, keys);
- set_representation(Representation::Tagged());
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- HValue* enumerable() { return OperandAt(0); }
- HValue* map() { return OperandAt(1); }
- int idx() { return idx_; }
-
- HForInCacheArray* index_cache() {
- return index_cache_;
- }
-
- void set_index_cache(HForInCacheArray* index_cache) {
- index_cache_ = index_cache;
- }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual HType CalculateInferredType() {
- return HType::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
-
- private:
- int idx_;
- HForInCacheArray* index_cache_;
-};
-
-
-class HLoadFieldByIndex : public HTemplateInstruction<2> {
- public:
- HLoadFieldByIndex(HValue* object,
- HValue* index) {
- SetOperandAt(0, object);
- SetOperandAt(1, index);
- set_representation(Representation::Tagged());
- }
-
- virtual Representation RequiredInputRepresentation(int index) {
- return Representation::Tagged();
- }
-
- HValue* object() { return OperandAt(0); }
- HValue* index() { return OperandAt(1); }
-
- virtual void PrintDataTo(StringStream* stream);
-
- virtual HType CalculateInferredType() {
- return HType::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
-
- private:
- virtual bool IsDeletable() const { return true; }
-};
-
-
-#undef DECLARE_INSTRUCTION
-#undef DECLARE_CONCRETE_INSTRUCTION
-
-} } // namespace v8::internal
-
-#endif // V8_HYDROGEN_INSTRUCTIONS_H_