| Index: src/hydrogen-instructions.h
|
| diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
|
| index c36388ee6abd359898fe1f57134b8e9f19311d81..eac5173f7d00748bec37cba8a7bb68990113342c 100644
|
| --- a/src/hydrogen-instructions.h
|
| +++ b/src/hydrogen-instructions.h
|
| @@ -135,7 +135,6 @@ class LChunkBuilder;
|
| V(IsSmiAndBranch) \
|
| V(IsUndetectableAndBranch) \
|
| V(LeaveInlined) \
|
| - V(LinkObjectInList) \
|
| V(LoadContextSlot) \
|
| V(LoadExternalArrayPointer) \
|
| V(LoadFieldByIndex) \
|
| @@ -179,7 +178,6 @@ class LChunkBuilder;
|
| V(StringCharCodeAt) \
|
| V(StringCharFromCode) \
|
| V(StringCompareAndBranch) \
|
| - V(StringLength) \
|
| V(Sub) \
|
| V(ThisFunction) \
|
| V(Throw) \
|
| @@ -201,6 +199,7 @@ class LChunkBuilder;
|
| #define GVN_UNTRACKED_FLAG_LIST(V) \
|
| V(ArrayElements) \
|
| V(ArrayLengths) \
|
| + V(StringLengths) \
|
| V(BackingStoreFields) \
|
| V(Calls) \
|
| V(ContextSlots) \
|
| @@ -211,7 +210,7 @@ class LChunkBuilder;
|
| V(GlobalVars) \
|
| V(InobjectFields) \
|
| V(OsrEntries) \
|
| - V(SpecializedArrayElements)
|
| + V(ExternalMemory)
|
|
|
|
|
| #define DECLARE_ABSTRACT_INSTRUCTION(type) \
|
| @@ -350,8 +349,7 @@ class UniqueValueId {
|
|
|
| class HType {
|
| public:
|
| - HType() : type_(kUninitialized) { }
|
| -
|
| + static HType None() { return HType(kNone); }
|
| static HType Tagged() { return HType(kTagged); }
|
| static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
|
| static HType TaggedNumber() { return HType(kTaggedNumber); }
|
| @@ -362,7 +360,6 @@ class HType {
|
| 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) {
|
| @@ -378,32 +375,26 @@ class HType {
|
| }
|
|
|
| bool IsTagged() const {
|
| - ASSERT(type_ != kUninitialized);
|
| return ((type_ & kTagged) == kTagged);
|
| }
|
|
|
| bool IsTaggedPrimitive() const {
|
| - ASSERT(type_ != kUninitialized);
|
| return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
|
| }
|
|
|
| bool IsTaggedNumber() const {
|
| - ASSERT(type_ != kUninitialized);
|
| return ((type_ & kTaggedNumber) == kTaggedNumber);
|
| }
|
|
|
| bool IsSmi() const {
|
| - ASSERT(type_ != kUninitialized);
|
| return ((type_ & kSmi) == kSmi);
|
| }
|
|
|
| bool IsHeapNumber() const {
|
| - ASSERT(type_ != kUninitialized);
|
| return ((type_ & kHeapNumber) == kHeapNumber);
|
| }
|
|
|
| bool IsString() const {
|
| - ASSERT(type_ != kUninitialized);
|
| return ((type_ & kString) == kString);
|
| }
|
|
|
| @@ -413,40 +404,50 @@ class HType {
|
| }
|
|
|
| bool IsBoolean() const {
|
| - ASSERT(type_ != kUninitialized);
|
| return ((type_ & kBoolean) == kBoolean);
|
| }
|
|
|
| bool IsNonPrimitive() const {
|
| - ASSERT(type_ != kUninitialized);
|
| return ((type_ & kNonPrimitive) == kNonPrimitive);
|
| }
|
|
|
| bool IsJSArray() const {
|
| - ASSERT(type_ != kUninitialized);
|
| return ((type_ & kJSArray) == kJSArray);
|
| }
|
|
|
| bool IsJSObject() const {
|
| - ASSERT(type_ != kUninitialized);
|
| return ((type_ & kJSObject) == kJSObject);
|
| }
|
|
|
| - bool IsUninitialized() const {
|
| - return type_ == kUninitialized;
|
| - }
|
| -
|
| bool IsHeapObject() const {
|
| - ASSERT(type_ != kUninitialized);
|
| return IsHeapNumber() || IsString() || IsBoolean() || IsNonPrimitive();
|
| }
|
|
|
| + bool ToStringOrToNumberCanBeObserved(Representation representation) {
|
| + switch (type_) {
|
| + case kTaggedPrimitive: // fallthru
|
| + case kTaggedNumber: // fallthru
|
| + case kSmi: // fallthru
|
| + case kHeapNumber: // fallthru
|
| + case kString: // fallthru
|
| + case kBoolean:
|
| + return false;
|
| + case kJSArray: // fallthru
|
| + case kJSObject:
|
| + return true;
|
| + case kTagged:
|
| + break;
|
| + }
|
| + return !representation.IsSmiOrInteger32() && !representation.IsDouble();
|
| + }
|
| +
|
| static HType TypeFromValue(Handle<Object> value);
|
|
|
| const char* ToString();
|
|
|
| private:
|
| enum Type {
|
| + kNone = 0x0, // 0000 0000 0000 0000
|
| kTagged = 0x1, // 0000 0000 0000 0001
|
| kTaggedPrimitive = 0x5, // 0000 0000 0000 0101
|
| kTaggedNumber = 0xd, // 0000 0000 0000 1101
|
| @@ -456,12 +457,11 @@ class HType {
|
| 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
|
| + kJSArray = 0x701 // 0000 0111 0000 0001
|
| };
|
|
|
| // Make sure type fits in int16.
|
| - STATIC_ASSERT(kUninitialized < (1 << (2 * kBitsPerByte)));
|
| + STATIC_ASSERT(kJSArray < (1 << (2 * kBitsPerByte)));
|
|
|
| explicit HType(Type t) : type_(t) { }
|
|
|
| @@ -872,12 +872,13 @@ class HValue: public ZoneObject {
|
| HYDROGEN_ABSTRACT_INSTRUCTION_LIST(DECLARE_PREDICATE)
|
| #undef DECLARE_PREDICATE
|
|
|
| - HValue() : block_(NULL),
|
| - id_(kNoNumber),
|
| - type_(HType::Tagged()),
|
| - use_list_(NULL),
|
| - range_(NULL),
|
| - flags_(0) {}
|
| + HValue(HType type = HType::Tagged())
|
| + : block_(NULL),
|
| + id_(kNoNumber),
|
| + type_(type),
|
| + use_list_(NULL),
|
| + range_(NULL),
|
| + flags_(0) {}
|
| virtual ~HValue() {}
|
|
|
| HBasicBlock* block() const { return block_; }
|
| @@ -1145,6 +1146,18 @@ class HValue: public ZoneObject {
|
| }
|
| }
|
|
|
| + // Returns true conservatively if the program might be able to observe a
|
| + // ToString() operation on this value.
|
| + bool ToStringCanBeObserved() const {
|
| + return type().ToStringOrToNumberCanBeObserved(representation());
|
| + }
|
| +
|
| + // Returns true conservatively if the program might be able to observe a
|
| + // ToNumber() operation on this value.
|
| + bool ToNumberCanBeObserved() const {
|
| + return type().ToStringOrToNumberCanBeObserved(representation());
|
| + }
|
| +
|
| protected:
|
| void TryGuaranteeRangeRecursive(RangeEvaluationContext* context);
|
|
|
| @@ -1295,6 +1308,48 @@ class HValue: public ZoneObject {
|
| };
|
|
|
|
|
| +#define DECLARE_INSTRUCTION_FACTORY_P0(I) \
|
| + static I* New(Zone* zone, HValue* context) { \
|
| + return new(zone) I(); \
|
| +}
|
| +
|
| +#define DECLARE_INSTRUCTION_FACTORY_P1(I, P1) \
|
| + static I* New(Zone* zone, HValue* context, P1 p1) { \
|
| + return new(zone) I(p1); \
|
| + }
|
| +
|
| +#define DECLARE_INSTRUCTION_FACTORY_P2(I, P1, P2) \
|
| + static I* New(Zone* zone, HValue* context, P1 p1, P2 p2) { \
|
| + return new(zone) I(p1, p2); \
|
| + }
|
| +
|
| +#define DECLARE_INSTRUCTION_FACTORY_P3(I, P1, P2, P3) \
|
| + static I* New(Zone* zone, HValue* context, P1 p1, P2 p2, P3 p3) { \
|
| + return new(zone) I(p1, p2, p3); \
|
| + }
|
| +
|
| +#define DECLARE_INSTRUCTION_FACTORY_P4(I, P1, P2, P3, P4) \
|
| + static I* New(Zone* zone, \
|
| + HValue* context, \
|
| + P1 p1, \
|
| + P2 p2, \
|
| + P3 p3, \
|
| + P4 p4) { \
|
| + return new(zone) I(p1, p2, p3, p4); \
|
| + }
|
| +
|
| +#define DECLARE_INSTRUCTION_FACTORY_P5(I, P1, P2, P3, P4, P5) \
|
| + static I* New(Zone* zone, \
|
| + HValue* context, \
|
| + P1 p1, \
|
| + P2 p2, \
|
| + P3 p3, \
|
| + P4 p4, \
|
| + P5 p5) { \
|
| + return new(zone) I(p1, p2, p3, p4, p5); \
|
| + }
|
| +
|
| +
|
| class HInstruction: public HValue {
|
| public:
|
| HInstruction* next() const { return next_; }
|
| @@ -1330,8 +1385,9 @@ class HInstruction: public HValue {
|
| DECLARE_ABSTRACT_INSTRUCTION(Instruction)
|
|
|
| protected:
|
| - HInstruction()
|
| - : next_(NULL),
|
| + HInstruction(HType type = HType::Tagged())
|
| + : HValue(type),
|
| + next_(NULL),
|
| previous_(NULL),
|
| position_(RelocInfo::kNoPosition) {
|
| SetGVNFlag(kDependsOnOsrEntries);
|
| @@ -1362,6 +1418,8 @@ class HTemplateInstruction : public HInstruction {
|
| HValue* OperandAt(int i) const { return inputs_[i]; }
|
|
|
| protected:
|
| + HTemplateInstruction(HType type = HType::Tagged()) : HInstruction(type) {}
|
| +
|
| void InternalSetOperandAt(int i, HValue* value) { inputs_[i] = value; }
|
|
|
| private:
|
| @@ -1435,12 +1493,12 @@ class HBlockEntry: public HTemplateInstruction<0> {
|
|
|
| class HDummyUse: public HTemplateInstruction<1> {
|
| public:
|
| - explicit HDummyUse(HValue* value) {
|
| + explicit HDummyUse(HValue* value)
|
| + : HTemplateInstruction<1>(HType::Smi()) {
|
| SetOperandAt(0, value);
|
| // Pretend to be a Smi so that the HChange instructions inserted
|
| // before any use generate as little code as possible.
|
| set_representation(Representation::Tagged());
|
| - set_type(HType::Smi());
|
| }
|
|
|
| HValue* value() { return OperandAt(0); }
|
| @@ -1504,7 +1562,7 @@ class HNumericConstraint : public HTemplateInstruction<2> {
|
|
|
| class HDeoptimize: public HTemplateInstruction<0> {
|
| public:
|
| - explicit HDeoptimize(Deoptimizer::BailoutType type) : type_(type) {}
|
| + DECLARE_INSTRUCTION_FACTORY_P1(HDeoptimize, Deoptimizer::BailoutType);
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| return Representation::None();
|
| @@ -1515,6 +1573,8 @@ class HDeoptimize: public HTemplateInstruction<0> {
|
| DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
|
|
|
| private:
|
| + explicit HDeoptimize(Deoptimizer::BailoutType type) : type_(type) {}
|
| +
|
| Deoptimizer::BailoutType type_;
|
| };
|
|
|
| @@ -1615,12 +1675,44 @@ class HCompareMap: public HUnaryControlInstruction {
|
| };
|
|
|
|
|
| +class HContext: public HTemplateInstruction<0> {
|
| + public:
|
| + static HContext* New(Zone* zone) {
|
| + return new(zone) HContext();
|
| + }
|
| +
|
| + virtual Representation RequiredInputRepresentation(int index) {
|
| + return Representation::None();
|
| + }
|
| +
|
| + DECLARE_CONCRETE_INSTRUCTION(Context)
|
| +
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) { return true; }
|
| +
|
| + private:
|
| + HContext() {
|
| + set_representation(Representation::Tagged());
|
| + SetFlag(kUseGVN);
|
| + }
|
| +
|
| + virtual bool IsDeletable() const { return true; }
|
| +};
|
| +
|
| +
|
| class HReturn: public HTemplateControlInstruction<0, 3> {
|
| public:
|
| - HReturn(HValue* value, HValue* context, HValue* parameter_count) {
|
| - SetOperandAt(0, value);
|
| - SetOperandAt(1, context);
|
| - SetOperandAt(2, parameter_count);
|
| + static HInstruction* New(Zone* zone,
|
| + HValue* context,
|
| + HValue* value,
|
| + HValue* parameter_count) {
|
| + return new(zone) HReturn(value, context, parameter_count);
|
| + }
|
| +
|
| + static HInstruction* New(Zone* zone,
|
| + HValue* context,
|
| + HValue* value) {
|
| + return new(zone) HReturn(value, context, 0);
|
| }
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| @@ -1634,6 +1726,13 @@ class HReturn: public HTemplateControlInstruction<0, 3> {
|
| HValue* parameter_count() { return OperandAt(2); }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(Return)
|
| +
|
| + private:
|
| + HReturn(HValue* value, HValue* context, HValue* parameter_count) {
|
| + SetOperandAt(0, value);
|
| + SetOperandAt(1, context);
|
| + SetOperandAt(2, parameter_count);
|
| + }
|
| };
|
|
|
|
|
| @@ -1649,7 +1748,8 @@ class HAbnormalExit: public HTemplateControlInstruction<0, 0> {
|
|
|
| class HUnaryOperation: public HTemplateInstruction<1> {
|
| public:
|
| - explicit HUnaryOperation(HValue* value) {
|
| + HUnaryOperation(HValue* value, HType type = HType::Tagged())
|
| + : HTemplateInstruction<1>(type) {
|
| SetOperandAt(0, value);
|
| }
|
|
|
| @@ -1664,10 +1764,10 @@ class HUnaryOperation: public HTemplateInstruction<1> {
|
|
|
| class HThrow: public HTemplateInstruction<2> {
|
| public:
|
| - HThrow(HValue* context, HValue* value) {
|
| - SetOperandAt(0, context);
|
| - SetOperandAt(1, value);
|
| - SetAllSideEffects();
|
| + static HThrow* New(Zone* zone,
|
| + HValue* context,
|
| + HValue* value) {
|
| + return new(zone) HThrow(context, value);
|
| }
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| @@ -1678,27 +1778,34 @@ class HThrow: public HTemplateInstruction<2> {
|
| HValue* value() { return OperandAt(1); }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(Throw)
|
| +
|
| + private:
|
| + HThrow(HValue* context, HValue* value) {
|
| + SetOperandAt(0, context);
|
| + SetOperandAt(1, value);
|
| + SetAllSideEffects();
|
| + }
|
| };
|
|
|
|
|
| class HUseConst: public HUnaryOperation {
|
| public:
|
| - explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
|
| + DECLARE_INSTRUCTION_FACTORY_P1(HUseConst, HValue*);
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| return Representation::None();
|
| }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(UseConst)
|
| +
|
| + private:
|
| + explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
|
| };
|
|
|
|
|
| class HForceRepresentation: public HTemplateInstruction<1> {
|
| public:
|
| - HForceRepresentation(HValue* value, Representation required_representation) {
|
| - SetOperandAt(0, value);
|
| - set_representation(required_representation);
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P2(HForceRepresentation, HValue*, Representation);
|
|
|
| HValue* value() { return OperandAt(0); }
|
|
|
| @@ -1711,6 +1818,12 @@ class HForceRepresentation: public HTemplateInstruction<1> {
|
| virtual void PrintDataTo(StringStream* stream);
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation)
|
| +
|
| + private:
|
| + HForceRepresentation(HValue* value, Representation required_representation) {
|
| + SetOperandAt(0, value);
|
| + set_representation(required_representation);
|
| + }
|
| };
|
|
|
|
|
| @@ -1772,12 +1885,7 @@ class HChange: public HUnaryOperation {
|
|
|
| class HClampToUint8: public HUnaryOperation {
|
| public:
|
| - explicit HClampToUint8(HValue* value)
|
| - : HUnaryOperation(value) {
|
| - set_representation(Representation::Integer32());
|
| - SetFlag(kAllowUndefinedAsNaN);
|
| - SetFlag(kUseGVN);
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P1(HClampToUint8, HValue*);
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| return Representation::None();
|
| @@ -1789,6 +1897,13 @@ class HClampToUint8: public HUnaryOperation {
|
| virtual bool DataEquals(HValue* other) { return true; }
|
|
|
| private:
|
| + explicit HClampToUint8(HValue* value)
|
| + : HUnaryOperation(value) {
|
| + set_representation(Representation::Integer32());
|
| + SetFlag(kAllowUndefinedAsNaN);
|
| + SetFlag(kUseGVN);
|
| + }
|
| +
|
| virtual bool IsDeletable() const { return true; }
|
| };
|
|
|
| @@ -1945,10 +2060,7 @@ class HStackCheck: public HTemplateInstruction<1> {
|
| kBackwardsBranch
|
| };
|
|
|
| - HStackCheck(HValue* context, Type type) : type_(type) {
|
| - SetOperandAt(0, context);
|
| - SetGVNFlag(kChangesNewSpacePromotion);
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P2(HStackCheck, HValue*, Type);
|
|
|
| HValue* context() { return OperandAt(0); }
|
|
|
| @@ -1970,6 +2082,11 @@ class HStackCheck: public HTemplateInstruction<1> {
|
| DECLARE_CONCRETE_INSTRUCTION(StackCheck)
|
|
|
| private:
|
| + HStackCheck(HValue* context, Type type) : type_(type) {
|
| + SetOperandAt(0, context);
|
| + SetGVNFlag(kChangesNewSpacePromotion);
|
| + }
|
| +
|
| Type type_;
|
| };
|
|
|
| @@ -1988,23 +2105,18 @@ class HArgumentsObject;
|
|
|
| class HEnterInlined: public HTemplateInstruction<0> {
|
| public:
|
| - HEnterInlined(Handle<JSFunction> closure,
|
| - int arguments_count,
|
| - FunctionLiteral* function,
|
| - InliningKind inlining_kind,
|
| - Variable* arguments_var,
|
| - HArgumentsObject* arguments_object,
|
| - bool undefined_receiver,
|
| - Zone* zone)
|
| - : closure_(closure),
|
| - arguments_count_(arguments_count),
|
| - arguments_pushed_(false),
|
| - function_(function),
|
| - inlining_kind_(inlining_kind),
|
| - arguments_var_(arguments_var),
|
| - arguments_object_(arguments_object),
|
| - undefined_receiver_(undefined_receiver),
|
| - return_targets_(2, zone) {
|
| + static HEnterInlined* New(Zone* zone,
|
| + HValue* context,
|
| + Handle<JSFunction> closure,
|
| + int arguments_count,
|
| + FunctionLiteral* function,
|
| + InliningKind inlining_kind,
|
| + Variable* arguments_var,
|
| + HArgumentsObject* arguments_object,
|
| + bool undefined_receiver) {
|
| + return new(zone) HEnterInlined(closure, arguments_count, function,
|
| + inlining_kind, arguments_var,
|
| + arguments_object, undefined_receiver, zone);
|
| }
|
|
|
| void RegisterReturnTarget(HBasicBlock* return_target, Zone* zone);
|
| @@ -2030,6 +2142,25 @@ class HEnterInlined: public HTemplateInstruction<0> {
|
| DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
|
|
|
| private:
|
| + HEnterInlined(Handle<JSFunction> closure,
|
| + int arguments_count,
|
| + FunctionLiteral* function,
|
| + InliningKind inlining_kind,
|
| + Variable* arguments_var,
|
| + HArgumentsObject* arguments_object,
|
| + bool undefined_receiver,
|
| + Zone* zone)
|
| + : closure_(closure),
|
| + arguments_count_(arguments_count),
|
| + arguments_pushed_(false),
|
| + function_(function),
|
| + inlining_kind_(inlining_kind),
|
| + arguments_var_(arguments_var),
|
| + arguments_object_(arguments_object),
|
| + undefined_receiver_(undefined_receiver),
|
| + return_targets_(2, zone) {
|
| + }
|
| +
|
| Handle<JSFunction> closure_;
|
| int arguments_count_;
|
| bool arguments_pushed_;
|
| @@ -2056,9 +2187,7 @@ class HLeaveInlined: public HTemplateInstruction<0> {
|
|
|
| class HPushArgument: public HUnaryOperation {
|
| public:
|
| - explicit HPushArgument(HValue* value) : HUnaryOperation(value) {
|
| - set_representation(Representation::Tagged());
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P1(HPushArgument, HValue*);
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| return Representation::Tagged();
|
| @@ -2067,6 +2196,11 @@ class HPushArgument: public HUnaryOperation {
|
| HValue* argument() { return OperandAt(0); }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(PushArgument)
|
| +
|
| + private:
|
| + explicit HPushArgument(HValue* value) : HUnaryOperation(value) {
|
| + set_representation(Representation::Tagged());
|
| + }
|
| };
|
|
|
|
|
| @@ -2091,44 +2225,25 @@ class HThisFunction: public HTemplateInstruction<0> {
|
| };
|
|
|
|
|
| -class HContext: public HTemplateInstruction<0> {
|
| +class HOuterContext: public HUnaryOperation {
|
| public:
|
| - HContext() {
|
| - set_representation(Representation::Tagged());
|
| - SetFlag(kUseGVN);
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P1(HOuterContext, HValue*);
|
| +
|
| + DECLARE_CONCRETE_INSTRUCTION(OuterContext);
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| - return Representation::None();
|
| + return Representation::Tagged();
|
| }
|
|
|
| - 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; }
|
| };
|
|
|
| @@ -2145,6 +2260,13 @@ class HDeclareGlobals: public HUnaryOperation {
|
| SetAllSideEffects();
|
| }
|
|
|
| + static HDeclareGlobals* New(Zone* zone,
|
| + HValue* context,
|
| + Handle<FixedArray> pairs,
|
| + int flags) {
|
| + return new(zone) HDeclareGlobals(context, pairs, flags);
|
| + }
|
| +
|
| HValue* context() { return OperandAt(0); }
|
| Handle<FixedArray> pairs() const { return pairs_; }
|
| int flags() const { return flags_; }
|
| @@ -2154,6 +2276,7 @@ class HDeclareGlobals: public HUnaryOperation {
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| return Representation::Tagged();
|
| }
|
| +
|
| private:
|
| Handle<FixedArray> pairs_;
|
| int flags_;
|
| @@ -2167,6 +2290,10 @@ class HGlobalObject: public HUnaryOperation {
|
| SetFlag(kUseGVN);
|
| }
|
|
|
| + static HGlobalObject* New(Zone* zone, HValue* context) {
|
| + return new(zone) HGlobalObject(context);
|
| + }
|
| +
|
| DECLARE_CONCRETE_INSTRUCTION(GlobalObject)
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| @@ -2183,11 +2310,7 @@ class HGlobalObject: public HUnaryOperation {
|
|
|
| class HGlobalReceiver: public HUnaryOperation {
|
| public:
|
| - explicit HGlobalReceiver(HValue* global_object)
|
| - : HUnaryOperation(global_object) {
|
| - set_representation(Representation::Tagged());
|
| - SetFlag(kUseGVN);
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P1(HGlobalReceiver, HValue*);
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver)
|
|
|
| @@ -2199,6 +2322,12 @@ class HGlobalReceiver: public HUnaryOperation {
|
| virtual bool DataEquals(HValue* other) { return true; }
|
|
|
| private:
|
| + explicit HGlobalReceiver(HValue* global_object)
|
| + : HUnaryOperation(global_object) {
|
| + set_representation(Representation::Tagged());
|
| + SetFlag(kUseGVN);
|
| + }
|
| +
|
| virtual bool IsDeletable() const { return true; }
|
| };
|
|
|
| @@ -2265,6 +2394,13 @@ class HInvokeFunction: public HBinaryCall {
|
| : HBinaryCall(context, function, argument_count) {
|
| }
|
|
|
| + static HInvokeFunction* New(Zone* zone,
|
| + HValue* context,
|
| + HValue* function,
|
| + int argument_count) {
|
| + return new(zone) HInvokeFunction(context, function, argument_count);
|
| + }
|
| +
|
| HInvokeFunction(HValue* context,
|
| HValue* function,
|
| Handle<JSFunction> known_function,
|
| @@ -2275,6 +2411,15 @@ class HInvokeFunction: public HBinaryCall {
|
| ? 0 : known_function->shared()->formal_parameter_count();
|
| }
|
|
|
| + static HInvokeFunction* New(Zone* zone,
|
| + HValue* context,
|
| + HValue* function,
|
| + Handle<JSFunction> known_function,
|
| + int argument_count) {
|
| + return new(zone) HInvokeFunction(context, function,
|
| + known_function, argument_count);
|
| + }
|
| +
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| return Representation::Tagged();
|
| }
|
| @@ -2366,6 +2511,13 @@ class HCallFunction: public HBinaryCall {
|
| : HBinaryCall(context, function, argument_count) {
|
| }
|
|
|
| + static HCallFunction* New(Zone* zone,
|
| + HValue* context,
|
| + HValue* function,
|
| + int argument_count) {
|
| + return new(zone) HCallFunction(context, function, argument_count);
|
| + }
|
| +
|
| HValue* context() { return first(); }
|
| HValue* function() { return second(); }
|
|
|
| @@ -2383,6 +2535,13 @@ class HCallGlobal: public HUnaryCall {
|
| : HUnaryCall(context, argument_count), name_(name) {
|
| }
|
|
|
| + static HCallGlobal* New(Zone* zone,
|
| + HValue* context,
|
| + Handle<String> name,
|
| + int argument_count) {
|
| + return new(zone) HCallGlobal(context, name, argument_count);
|
| + }
|
| +
|
| virtual void PrintDataTo(StringStream* stream);
|
|
|
| HValue* context() { return value(); }
|
| @@ -2466,12 +2625,12 @@ class HCallNewArray: public HCallNew {
|
|
|
| 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);
|
| + static HCallRuntime* New(Zone* zone,
|
| + HValue* context,
|
| + Handle<String> name,
|
| + const Runtime::Function* c_function,
|
| + int argument_count) {
|
| + return new(zone) HCallRuntime(context, name, c_function, argument_count);
|
| }
|
|
|
| virtual void PrintDataTo(StringStream* stream);
|
| @@ -2487,6 +2646,14 @@ class HCallRuntime: public HCall<1> {
|
| DECLARE_CONCRETE_INSTRUCTION(CallRuntime)
|
|
|
| private:
|
| + 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);
|
| + }
|
| +
|
| const Runtime::Function* c_function_;
|
| Handle<String> name_;
|
| };
|
| @@ -2494,12 +2661,7 @@ class HCallRuntime: public HCall<1> {
|
|
|
| class HMapEnumLength: public HUnaryOperation {
|
| public:
|
| - explicit HMapEnumLength(HValue* value) : HUnaryOperation(value) {
|
| - set_type(HType::Smi());
|
| - set_representation(Representation::Smi());
|
| - SetFlag(kUseGVN);
|
| - SetGVNFlag(kDependsOnMaps);
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P1(HMapEnumLength, HValue*);
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| return Representation::Tagged();
|
| @@ -2511,6 +2673,13 @@ class HMapEnumLength: public HUnaryOperation {
|
| virtual bool DataEquals(HValue* other) { return true; }
|
|
|
| private:
|
| + explicit HMapEnumLength(HValue* value)
|
| + : HUnaryOperation(value, HType::Smi()) {
|
| + set_representation(Representation::Smi());
|
| + SetFlag(kUseGVN);
|
| + SetGVNFlag(kDependsOnMaps);
|
| + }
|
| +
|
| virtual bool IsDeletable() const { return true; }
|
| };
|
|
|
| @@ -2539,12 +2708,7 @@ class HElementsKind: public HUnaryOperation {
|
|
|
| class HBitNot: public HUnaryOperation {
|
| public:
|
| - explicit HBitNot(HValue* value) : HUnaryOperation(value) {
|
| - set_representation(Representation::Integer32());
|
| - SetFlag(kUseGVN);
|
| - SetFlag(kTruncatingToInt32);
|
| - SetFlag(kAllowUndefinedAsNaN);
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P1(HBitNot, HValue*);
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| return Representation::Integer32();
|
| @@ -2552,7 +2716,6 @@ class HBitNot: public HUnaryOperation {
|
| virtual Representation observed_input_representation(int index) {
|
| return Representation::Integer32();
|
| }
|
| - virtual HType CalculateInferredType();
|
|
|
| virtual HValue* Canonicalize();
|
|
|
| @@ -2562,6 +2725,14 @@ class HBitNot: public HUnaryOperation {
|
| virtual bool DataEquals(HValue* other) { return true; }
|
|
|
| private:
|
| + explicit HBitNot(HValue* value)
|
| + : HUnaryOperation(value, HType::TaggedNumber()) {
|
| + set_representation(Representation::Integer32());
|
| + SetFlag(kUseGVN);
|
| + SetFlag(kTruncatingToInt32);
|
| + SetFlag(kAllowUndefinedAsNaN);
|
| + }
|
| +
|
| virtual bool IsDeletable() const { return true; }
|
| };
|
|
|
| @@ -2578,8 +2749,6 @@ class HUnaryMathOperation: public HTemplateInstruction<2> {
|
|
|
| virtual void PrintDataTo(StringStream* stream);
|
|
|
| - virtual HType CalculateInferredType();
|
| -
|
| virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| @@ -2624,7 +2793,7 @@ class HUnaryMathOperation: public HTemplateInstruction<2> {
|
|
|
| private:
|
| HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
|
| - : op_(op) {
|
| + : HTemplateInstruction<2>(HType::TaggedNumber()), op_(op) {
|
| SetOperandAt(0, context);
|
| SetOperandAt(1, value);
|
| switch (op) {
|
| @@ -2668,35 +2837,43 @@ class HUnaryMathOperation: public HTemplateInstruction<2> {
|
|
|
| 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);
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P1(HLoadExternalArrayPointer, HValue*);
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| return Representation::Tagged();
|
| }
|
|
|
| + virtual HType CalculateInferredType() {
|
| + return HType::None();
|
| + }
|
| +
|
| DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer)
|
|
|
| protected:
|
| virtual bool DataEquals(HValue* other) { return true; }
|
|
|
| private:
|
| + 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 bool IsDeletable() const { return true; }
|
| };
|
|
|
|
|
| class HCheckMaps: public HTemplateInstruction<2> {
|
| public:
|
| - static HCheckMaps* New(HValue* value, Handle<Map> map, Zone* zone,
|
| - CompilationInfo* info, HValue *typecheck = NULL);
|
| - static HCheckMaps* New(HValue* value, SmallMapList* maps, Zone* zone,
|
| + static HCheckMaps* New(Zone* zone, HValue* context, HValue* value,
|
| + Handle<Map> map, CompilationInfo* info,
|
| + HValue *typecheck = NULL);
|
| + static HCheckMaps* New(Zone* zone, HValue* context,
|
| + HValue* value, SmallMapList* maps,
|
| HValue *typecheck = NULL) {
|
| HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck);
|
| for (int i = 0; i < maps->length(); i++) {
|
| @@ -2706,9 +2883,6 @@ class HCheckMaps: public HTemplateInstruction<2> {
|
| return check_map;
|
| }
|
|
|
| - static HCheckMaps* NewWithTransitions(HValue* value, Handle<Map> map,
|
| - Zone* zone, CompilationInfo* info);
|
| -
|
| bool CanOmitMapChecks() { return omit_; }
|
|
|
| virtual bool HasEscapingOperandAt(int index) { return false; }
|
| @@ -2718,7 +2892,6 @@ class HCheckMaps: public HTemplateInstruction<2> {
|
| virtual void HandleSideEffectDominator(GVNFlag side_effect,
|
| HValue* dominator);
|
| virtual void PrintDataTo(StringStream* stream);
|
| - virtual HType CalculateInferredType();
|
|
|
| HValue* value() { return OperandAt(0); }
|
| SmallMapList* map_set() { return &map_set_; }
|
| @@ -2746,7 +2919,8 @@ class HCheckMaps: public HTemplateInstruction<2> {
|
| private:
|
| // Clients should use one of the static New* methods above.
|
| HCheckMaps(HValue* value, Zone *zone, HValue* typecheck)
|
| - : omit_(false), map_unique_ids_(0, zone) {
|
| + : HTemplateInstruction<2>(value->type()),
|
| + omit_(false), map_unique_ids_(0, zone) {
|
| SetOperandAt(0, value);
|
| // Use the object value for the dependency if NULL is passed.
|
| // TODO(titzer): do GVN flags already express this dependency?
|
| @@ -2775,18 +2949,12 @@ class HCheckMaps: public HTemplateInstruction<2> {
|
|
|
| class HCheckFunction: public HUnaryOperation {
|
| public:
|
| - HCheckFunction(HValue* value, Handle<JSFunction> function)
|
| - : HUnaryOperation(value), target_(function), target_unique_id_() {
|
| - set_representation(Representation::Tagged());
|
| - SetFlag(kUseGVN);
|
| - target_in_new_space_ = Isolate::Current()->heap()->InNewSpace(*function);
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P2(HCheckFunction, HValue*, Handle<JSFunction>);
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| return Representation::Tagged();
|
| }
|
| virtual void PrintDataTo(StringStream* stream);
|
| - virtual HType CalculateInferredType();
|
|
|
| virtual HValue* Canonicalize();
|
|
|
| @@ -2810,6 +2978,14 @@ class HCheckFunction: public HUnaryOperation {
|
| }
|
|
|
| private:
|
| + HCheckFunction(HValue* value, Handle<JSFunction> function)
|
| + : HUnaryOperation(value, value->type()),
|
| + target_(function), target_unique_id_() {
|
| + set_representation(Representation::Tagged());
|
| + SetFlag(kUseGVN);
|
| + target_in_new_space_ = Isolate::Current()->heap()->InNewSpace(*function);
|
| + }
|
| +
|
| Handle<JSFunction> target_;
|
| UniqueValueId target_unique_id_;
|
| bool target_in_new_space_;
|
| @@ -2878,17 +3054,12 @@ class HCheckInstanceType: public HUnaryOperation {
|
|
|
| class HCheckSmi: public HUnaryOperation {
|
| public:
|
| - explicit HCheckSmi(HValue* value) : HUnaryOperation(value) {
|
| - set_representation(Representation::Smi());
|
| - SetFlag(kUseGVN);
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P1(HCheckSmi, HValue*);
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| return Representation::Tagged();
|
| }
|
|
|
| - virtual HType CalculateInferredType();
|
| -
|
| virtual HValue* Canonicalize() {
|
| HType value_type = value()->type();
|
| if (value_type.IsSmi()) {
|
| @@ -2901,6 +3072,12 @@ class HCheckSmi: public HUnaryOperation {
|
|
|
| protected:
|
| virtual bool DataEquals(HValue* other) { return true; }
|
| +
|
| + private:
|
| + explicit HCheckSmi(HValue* value) : HUnaryOperation(value, HType::Smi()) {
|
| + set_representation(Representation::Smi());
|
| + SetFlag(kUseGVN);
|
| + }
|
| };
|
|
|
|
|
| @@ -2921,67 +3098,42 @@ class HIsNumberAndBranch: public HUnaryControlInstruction {
|
|
|
| class HCheckHeapObject: public HUnaryOperation {
|
| public:
|
| - explicit HCheckHeapObject(HValue* value) : HUnaryOperation(value) {
|
| - set_representation(Representation::Tagged());
|
| - SetFlag(kUseGVN);
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P1(HCheckHeapObject, HValue*);
|
|
|
| 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.IsHeapObject()) {
|
| - return NULL;
|
| - }
|
| - return this;
|
| + return value()->type().IsHeapObject() ? NULL : this;
|
| }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject)
|
|
|
| protected:
|
| virtual bool DataEquals(HValue* other) { return true; }
|
| +
|
| + private:
|
| + explicit HCheckHeapObject(HValue* value)
|
| + : HUnaryOperation(value, HType::NonPrimitive()) {
|
| + set_representation(Representation::Tagged());
|
| + SetFlag(kUseGVN);
|
| + }
|
| };
|
|
|
|
|
| class HCheckPrototypeMaps: public HTemplateInstruction<0> {
|
| public:
|
| - HCheckPrototypeMaps(Handle<JSObject> prototype,
|
| - Handle<JSObject> holder,
|
| - Zone* zone,
|
| - CompilationInfo* info)
|
| - : prototypes_(2, zone),
|
| - maps_(2, zone),
|
| - first_prototype_unique_id_(),
|
| - last_prototype_unique_id_(),
|
| - can_omit_prototype_maps_(true) {
|
| - 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);
|
| - Handle<Map> map(prototype->map());
|
| - maps_.Add(map, zone);
|
| - can_omit_prototype_maps_ &= map->CanOmitPrototypeChecks();
|
| - if (prototype.is_identical_to(holder)) break;
|
| - prototype = Handle<JSObject>(JSObject::cast(prototype->GetPrototype()));
|
| - }
|
| - if (can_omit_prototype_maps_) {
|
| - // Mark in-flight compilation as dependent on those maps.
|
| - for (int i = 0; i < maps()->length(); i++) {
|
| - Handle<Map> map = maps()->at(i);
|
| - map->AddDependentCompilationInfo(DependentCode::kPrototypeCheckGroup,
|
| - info);
|
| - }
|
| - }
|
| + static HCheckPrototypeMaps* New(Zone* zone,
|
| + HValue* context,
|
| + Handle<JSObject> prototype,
|
| + Handle<JSObject> holder,
|
| + CompilationInfo* info) {
|
| + return new(zone) HCheckPrototypeMaps(prototype, holder, zone, info);
|
| }
|
|
|
| ZoneList<Handle<JSObject> >* prototypes() { return &prototypes_; }
|
| @@ -3016,6 +3168,37 @@ class HCheckPrototypeMaps: public HTemplateInstruction<0> {
|
| }
|
|
|
| private:
|
| + HCheckPrototypeMaps(Handle<JSObject> prototype,
|
| + Handle<JSObject> holder,
|
| + Zone* zone,
|
| + CompilationInfo* info)
|
| + : prototypes_(2, zone),
|
| + maps_(2, zone),
|
| + first_prototype_unique_id_(),
|
| + last_prototype_unique_id_(),
|
| + can_omit_prototype_maps_(true) {
|
| + 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);
|
| + Handle<Map> map(prototype->map());
|
| + maps_.Add(map, zone);
|
| + can_omit_prototype_maps_ &= map->CanOmitPrototypeChecks();
|
| + if (prototype.is_identical_to(holder)) break;
|
| + prototype = Handle<JSObject>(JSObject::cast(prototype->GetPrototype()));
|
| + }
|
| + if (can_omit_prototype_maps_) {
|
| + // Mark in-flight compilation as dependent on those maps.
|
| + for (int i = 0; i < maps()->length(); i++) {
|
| + Handle<Map> map = maps()->at(i);
|
| + map->AddDependentCompilationInfo(DependentCode::kPrototypeCheckGroup,
|
| + info);
|
| + }
|
| + }
|
| + }
|
| +
|
| ZoneList<Handle<JSObject> > prototypes_;
|
| ZoneList<Handle<Map> > maps_;
|
| UniqueValueId first_prototype_unique_id_;
|
| @@ -3343,9 +3526,6 @@ class HPhi: public HValue {
|
|
|
| void SimplifyConstantInputs();
|
|
|
| - // TODO(titzer): we can't eliminate the receiver for generating backtraces
|
| - virtual bool IsDeletable() const { return !IsReceiver(); }
|
| -
|
| protected:
|
| virtual void DeleteFromGraph();
|
| virtual void InternalSetOperandAt(int index, HValue* value) {
|
| @@ -3365,6 +3545,9 @@ class HPhi: public HValue {
|
| int indirect_uses_[Representation::kNumRepresentations];
|
| int phi_id_;
|
| InductionVariableData* induction_variable_data_;
|
| +
|
| + // TODO(titzer): we can't eliminate the receiver for generating backtraces
|
| + virtual bool IsDeletable() const { return !IsReceiver(); }
|
| };
|
|
|
|
|
| @@ -3417,9 +3600,10 @@ class HInductionVariableAnnotation : public HUnaryOperation {
|
|
|
| class HArgumentsObject: public HTemplateInstruction<0> {
|
| public:
|
| - HArgumentsObject(int count, Zone* zone) : values_(count, zone) {
|
| - set_representation(Representation::Tagged());
|
| - SetFlag(kIsArguments);
|
| + static HArgumentsObject* New(Zone* zone,
|
| + HValue* context,
|
| + int count) {
|
| + return new(zone) HArgumentsObject(count, zone);
|
| }
|
|
|
| const ZoneList<HValue*>* arguments_values() const { return &values_; }
|
| @@ -3446,6 +3630,11 @@ class HArgumentsObject: public HTemplateInstruction<0> {
|
| }
|
|
|
| private:
|
| + HArgumentsObject(int count, Zone* zone) : values_(count, zone) {
|
| + set_representation(Representation::Tagged());
|
| + SetFlag(kIsArguments);
|
| + }
|
| +
|
| virtual bool IsDeletable() const { return true; }
|
|
|
| ZoneList<HValue*> values_;
|
| @@ -3454,23 +3643,11 @@ class HArgumentsObject: public HTemplateInstruction<0> {
|
|
|
| class HConstant: public HTemplateInstruction<0> {
|
| public:
|
| - HConstant(Handle<Object> handle, Representation r = Representation::None());
|
| - HConstant(int32_t value,
|
| - Representation r = Representation::None(),
|
| - bool is_not_in_new_space = true,
|
| - Handle<Object> optional_handle = Handle<Object>::null());
|
| - HConstant(double value,
|
| - Representation r = Representation::None(),
|
| - bool is_not_in_new_space = true,
|
| - Handle<Object> optional_handle = Handle<Object>::null());
|
| - HConstant(Handle<Object> handle,
|
| - UniqueValueId unique_id,
|
| - Representation r,
|
| - HType type,
|
| - bool is_internalized_string,
|
| - bool is_not_in_new_space,
|
| - bool is_cell,
|
| - bool boolean_value);
|
| + DECLARE_INSTRUCTION_FACTORY_P1(HConstant, int32_t);
|
| + DECLARE_INSTRUCTION_FACTORY_P2(HConstant, int32_t, Representation);
|
| + DECLARE_INSTRUCTION_FACTORY_P1(HConstant, double);
|
| + DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Handle<Object>);
|
| + DECLARE_INSTRUCTION_FACTORY_P1(HConstant, ExternalReference);
|
|
|
| Handle<Object> handle() {
|
| if (handle_.is_null()) {
|
| @@ -3535,12 +3712,12 @@ class HConstant: public HTemplateInstruction<0> {
|
| if (HasSmiValue() && kSmiValueSize == 31) return Representation::Smi();
|
| if (HasInteger32Value()) return Representation::Integer32();
|
| if (HasNumberValue()) return Representation::Double();
|
| + if (HasExternalReferenceValue()) return Representation::External();
|
| return Representation::Tagged();
|
| }
|
|
|
| virtual bool EmitAtUses();
|
| virtual void PrintDataTo(StringStream* stream);
|
| - virtual HType CalculateInferredType();
|
| bool IsInteger() { return handle()->IsSmi(); }
|
| HConstant* CopyToRepresentation(Representation r, Zone* zone) const;
|
| Maybe<HConstant*> CopyToTruncatedInt32(Zone* zone);
|
| @@ -3577,7 +3754,7 @@ class HConstant: public HTemplateInstruction<0> {
|
| bool HasStringValue() const {
|
| if (has_double_value_ || has_int32_value_) return false;
|
| ASSERT(!handle_.is_null());
|
| - return type_from_value_.IsString();
|
| + return type_.IsString();
|
| }
|
| Handle<String> StringValue() const {
|
| ASSERT(HasStringValue());
|
| @@ -3587,6 +3764,13 @@ class HConstant: public HTemplateInstruction<0> {
|
| return HasStringValue() && is_internalized_string_;
|
| }
|
|
|
| + bool HasExternalReferenceValue() const {
|
| + return has_external_reference_value_;
|
| + }
|
| + ExternalReference ExternalReferenceValue() const {
|
| + return external_reference_value_;
|
| + }
|
| +
|
| bool BooleanValue() const { return boolean_value_; }
|
|
|
| virtual intptr_t Hashcode() {
|
| @@ -3594,6 +3778,8 @@ class HConstant: public HTemplateInstruction<0> {
|
| return static_cast<intptr_t>(int32_value_);
|
| } else if (has_double_value_) {
|
| return static_cast<intptr_t>(BitCast<int64_t>(double_value_));
|
| + } else if (has_external_reference_value_) {
|
| + return reinterpret_cast<intptr_t>(external_reference_value_.address());
|
| } else {
|
| ASSERT(!handle_.is_null());
|
| return unique_id_.Hashcode();
|
| @@ -3601,14 +3787,15 @@ class HConstant: public HTemplateInstruction<0> {
|
| }
|
|
|
| virtual void FinalizeUniqueValueId() {
|
| - if (!has_double_value_) {
|
| + if (!has_double_value_ && !has_external_reference_value_) {
|
| ASSERT(!handle_.is_null());
|
| unique_id_ = UniqueValueId(handle_);
|
| }
|
| }
|
|
|
| bool UniqueValueIdsMatch(UniqueValueId other) {
|
| - return !has_double_value_ && unique_id_ == other;
|
| + return !has_double_value_ && !has_external_reference_value_ &&
|
| + unique_id_ == other;
|
| }
|
|
|
| #ifdef DEBUG
|
| @@ -3629,6 +3816,10 @@ class HConstant: public HTemplateInstruction<0> {
|
| return other_constant->has_double_value_ &&
|
| BitCast<int64_t>(double_value_) ==
|
| BitCast<int64_t>(other_constant->double_value_);
|
| + } else if (has_external_reference_value_) {
|
| + return other_constant->has_external_reference_value_ &&
|
| + external_reference_value_ ==
|
| + other_constant->external_reference_value_;
|
| } else {
|
| ASSERT(!handle_.is_null());
|
| return !other_constant->handle_.is_null() &&
|
| @@ -3637,6 +3828,26 @@ class HConstant: public HTemplateInstruction<0> {
|
| }
|
|
|
| private:
|
| + friend class HGraph;
|
| + HConstant(Handle<Object> handle, Representation r = Representation::None());
|
| + HConstant(int32_t value,
|
| + Representation r = Representation::None(),
|
| + bool is_not_in_new_space = true,
|
| + Handle<Object> optional_handle = Handle<Object>::null());
|
| + HConstant(double value,
|
| + Representation r = Representation::None(),
|
| + bool is_not_in_new_space = true,
|
| + Handle<Object> optional_handle = Handle<Object>::null());
|
| + HConstant(Handle<Object> handle,
|
| + UniqueValueId unique_id,
|
| + Representation r,
|
| + HType type,
|
| + bool is_internalized_string,
|
| + bool is_not_in_new_space,
|
| + bool is_cell,
|
| + bool boolean_value);
|
| + explicit HConstant(ExternalReference reference);
|
| +
|
| void Initialize(Representation r);
|
|
|
| virtual bool IsDeletable() const { return true; }
|
| @@ -3656,20 +3867,23 @@ class HConstant: public HTemplateInstruction<0> {
|
| bool has_smi_value_ : 1;
|
| bool has_int32_value_ : 1;
|
| bool has_double_value_ : 1;
|
| + bool has_external_reference_value_ : 1;
|
| bool is_internalized_string_ : 1; // TODO(yangguo): make this part of HType.
|
| bool is_not_in_new_space_ : 1;
|
| bool is_cell_ : 1;
|
| bool boolean_value_ : 1;
|
| int32_t int32_value_;
|
| double double_value_;
|
| - HType type_from_value_;
|
| + ExternalReference external_reference_value_;
|
| };
|
|
|
|
|
| class HBinaryOperation: public HTemplateInstruction<3> {
|
| public:
|
| - HBinaryOperation(HValue* context, HValue* left, HValue* right)
|
| - : observed_output_representation_(Representation::None()) {
|
| + HBinaryOperation(HValue* context, HValue* left, HValue* right,
|
| + HType type = HType::Tagged())
|
| + : HTemplateInstruction<3>(type),
|
| + observed_output_representation_(Representation::None()) {
|
| ASSERT(left != NULL && right != NULL);
|
| SetOperandAt(0, context);
|
| SetOperandAt(1, left);
|
| @@ -3678,9 +3892,9 @@ class HBinaryOperation: public HTemplateInstruction<3> {
|
| observed_input_representation_[1] = Representation::None();
|
| }
|
|
|
| - HValue* context() { return OperandAt(0); }
|
| - HValue* left() { return OperandAt(1); }
|
| - HValue* right() { return OperandAt(2); }
|
| + HValue* context() const { return OperandAt(0); }
|
| + HValue* left() const { return OperandAt(1); }
|
| + HValue* right() const { return OperandAt(2); }
|
|
|
| // True if switching left and right operands likely generates better code.
|
| bool AreOperandsBetterSwitched() {
|
| @@ -3753,11 +3967,7 @@ class HBinaryOperation: public HTemplateInstruction<3> {
|
|
|
| class HWrapReceiver: public HTemplateInstruction<2> {
|
| public:
|
| - HWrapReceiver(HValue* receiver, HValue* function) {
|
| - set_representation(Representation::Tagged());
|
| - SetOperandAt(0, receiver);
|
| - SetOperandAt(1, function);
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P2(HWrapReceiver, HValue*, HValue*);
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| return Representation::Tagged();
|
| @@ -3771,6 +3981,13 @@ class HWrapReceiver: public HTemplateInstruction<2> {
|
| virtual void PrintDataTo(StringStream* stream);
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
|
| +
|
| + private:
|
| + HWrapReceiver(HValue* receiver, HValue* function) {
|
| + set_representation(Representation::Tagged());
|
| + SetOperandAt(0, receiver);
|
| + SetOperandAt(1, function);
|
| + }
|
| };
|
|
|
|
|
| @@ -3806,12 +4023,7 @@ class HApplyArguments: public HTemplateInstruction<4> {
|
|
|
| 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_INSTRUCTION_FACTORY_P1(HArgumentsElements, bool);
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
|
|
|
| @@ -3825,6 +4037,13 @@ class HArgumentsElements: public HTemplateInstruction<0> {
|
| virtual bool DataEquals(HValue* other) { return true; }
|
|
|
| private:
|
| + explicit HArgumentsElements(bool from_inlined) : from_inlined_(from_inlined) {
|
| + // The value produced by this instruction is a pointer into the stack
|
| + // that looks as if it was a smi because of alignment.
|
| + set_representation(Representation::Tagged());
|
| + SetFlag(kUseGVN);
|
| + }
|
| +
|
| virtual bool IsDeletable() const { return true; }
|
|
|
| bool from_inlined_;
|
| @@ -3833,10 +4052,7 @@ class HArgumentsElements: public HTemplateInstruction<0> {
|
|
|
| class HArgumentsLength: public HUnaryOperation {
|
| public:
|
| - explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
|
| - set_representation(Representation::Integer32());
|
| - SetFlag(kUseGVN);
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsLength, HValue*);
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| return Representation::Tagged();
|
| @@ -3848,6 +4064,11 @@ class HArgumentsLength: public HUnaryOperation {
|
| virtual bool DataEquals(HValue* other) { return true; }
|
|
|
| private:
|
| + explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
|
| + set_representation(Representation::Integer32());
|
| + SetFlag(kUseGVN);
|
| + }
|
| +
|
| virtual bool IsDeletable() const { return true; }
|
| };
|
|
|
| @@ -3886,23 +4107,11 @@ class HBoundsCheckBaseIndexInformation;
|
|
|
| class HBoundsCheck: public HTemplateInstruction<2> {
|
| public:
|
| - // Normally HBoundsCheck should be created using the
|
| - // HGraphBuilder::AddBoundsCheck() helper.
|
| - // However when building stubs, where we know that the arguments are Int32,
|
| - // it makes sense to invoke this constructor directly.
|
| - HBoundsCheck(HValue* index, HValue* length)
|
| - : skip_check_(false),
|
| - base_(NULL), offset_(0), scale_(0),
|
| - responsibility_direction_(DIRECTION_NONE),
|
| - allow_equality_(false) {
|
| - SetOperandAt(0, index);
|
| - SetOperandAt(1, length);
|
| - SetFlag(kFlexibleRepresentation);
|
| - SetFlag(kUseGVN);
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*);
|
|
|
| bool skip_check() const { return skip_check_; }
|
| void set_skip_check() { skip_check_ = true; }
|
| +
|
| HValue* base() { return base_; }
|
| int offset() { return offset_; }
|
| int scale() { return scale_; }
|
| @@ -3934,9 +4143,6 @@ class HBoundsCheck: public HTemplateInstruction<2> {
|
| virtual Representation RequiredInputRepresentation(int arg_index) {
|
| return representation();
|
| }
|
| - virtual bool IsDeletable() const {
|
| - return skip_check() && !FLAG_debug_code;
|
| - }
|
|
|
| virtual bool IsRelationTrueInternal(NumericRelation relation,
|
| HValue* related_value,
|
| @@ -3973,6 +4179,26 @@ class HBoundsCheck: public HTemplateInstruction<2> {
|
| int scale_;
|
| RangeGuaranteeDirection responsibility_direction_;
|
| bool allow_equality_;
|
| +
|
| + private:
|
| + // Normally HBoundsCheck should be created using the
|
| + // HGraphBuilder::AddBoundsCheck() helper.
|
| + // However when building stubs, where we know that the arguments are Int32,
|
| + // it makes sense to invoke this constructor directly.
|
| + HBoundsCheck(HValue* index, HValue* length)
|
| + : skip_check_(false),
|
| + base_(NULL), offset_(0), scale_(0),
|
| + responsibility_direction_(DIRECTION_NONE),
|
| + allow_equality_(false) {
|
| + SetOperandAt(0, index);
|
| + SetOperandAt(1, length);
|
| + SetFlag(kFlexibleRepresentation);
|
| + SetFlag(kUseGVN);
|
| + }
|
| +
|
| + virtual bool IsDeletable() const {
|
| + return skip_check() && !FLAG_debug_code;
|
| + }
|
| };
|
|
|
|
|
| @@ -4018,8 +4244,9 @@ class HBoundsCheckBaseIndexInformation: public HTemplateInstruction<2> {
|
|
|
| class HBitwiseBinaryOperation: public HBinaryOperation {
|
| public:
|
| - HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right)
|
| - : HBinaryOperation(context, left, right) {
|
| + HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right,
|
| + HType type = HType::Tagged())
|
| + : HBinaryOperation(context, left, right, type) {
|
| SetFlag(kFlexibleRepresentation);
|
| SetFlag(kTruncatingToInt32);
|
| SetFlag(kAllowUndefinedAsNaN);
|
| @@ -4056,8 +4283,6 @@ class HBitwiseBinaryOperation: public HBinaryOperation {
|
| HBinaryOperation::initialize_output_representation(observed);
|
| }
|
|
|
| - virtual HType CalculateInferredType();
|
| -
|
| DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
|
|
|
| private:
|
| @@ -4067,15 +4292,11 @@ class HBitwiseBinaryOperation: public HBinaryOperation {
|
|
|
| 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);
|
| - }
|
| - SetFlag(kAllowUndefinedAsNaN);
|
| + static HMathFloorOfDiv* New(Zone* zone,
|
| + HValue* context,
|
| + HValue* left,
|
| + HValue* right) {
|
| + return new(zone) HMathFloorOfDiv(context, left, right);
|
| }
|
|
|
| virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
|
| @@ -4090,6 +4311,17 @@ class HMathFloorOfDiv: public HBinaryOperation {
|
| virtual bool DataEquals(HValue* other) { return true; }
|
|
|
| private:
|
| + HMathFloorOfDiv(HValue* context, HValue* left, HValue* right)
|
| + : HBinaryOperation(context, left, right) {
|
| + set_representation(Representation::Integer32());
|
| + SetFlag(kUseGVN);
|
| + SetFlag(kCanOverflow);
|
| + if (!right->IsConstant()) {
|
| + SetFlag(kCanBeDivByZero);
|
| + }
|
| + SetFlag(kAllowUndefinedAsNaN);
|
| + }
|
| +
|
| virtual bool IsDeletable() const { return true; }
|
| };
|
|
|
| @@ -4097,7 +4329,7 @@ class HMathFloorOfDiv: public HBinaryOperation {
|
| class HArithmeticBinaryOperation: public HBinaryOperation {
|
| public:
|
| HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right)
|
| - : HBinaryOperation(context, left, right) {
|
| + : HBinaryOperation(context, left, right, HType::TaggedNumber()) {
|
| SetAllSideEffects();
|
| SetFlag(kFlexibleRepresentation);
|
| SetFlag(kAllowUndefinedAsNaN);
|
| @@ -4113,8 +4345,6 @@ class HArithmeticBinaryOperation: public HBinaryOperation {
|
| }
|
| }
|
|
|
| - virtual HType CalculateInferredType();
|
| -
|
| DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)
|
|
|
| private:
|
| @@ -4128,7 +4358,8 @@ class HCompareGeneric: public HBinaryOperation {
|
| HValue* left,
|
| HValue* right,
|
| Token::Value token)
|
| - : HBinaryOperation(context, left, right), token_(token) {
|
| + : HBinaryOperation(context, left, right, HType::Boolean()),
|
| + token_(token) {
|
| ASSERT(Token::IsCompareOp(token));
|
| set_representation(Representation::Tagged());
|
| SetAllSideEffects();
|
| @@ -4143,8 +4374,6 @@ class HCompareGeneric: public HBinaryOperation {
|
| Token::Value token() const { return token_; }
|
| virtual void PrintDataTo(StringStream* stream);
|
|
|
| - virtual HType CalculateInferredType();
|
| -
|
| DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
|
|
|
| private:
|
| @@ -4194,11 +4423,16 @@ class HCompareNumericAndBranch: public HTemplateControlInstruction<2, 2> {
|
|
|
| class HCompareObjectEqAndBranch: public HTemplateControlInstruction<2, 2> {
|
| public:
|
| - HCompareObjectEqAndBranch(HValue* left, HValue* right) {
|
| + // TODO(danno): make this private when the IfBuilder properly constructs
|
| + // control flow instructions.
|
| + HCompareObjectEqAndBranch(HValue* left,
|
| + HValue* right) {
|
| SetOperandAt(0, left);
|
| SetOperandAt(1, right);
|
| }
|
|
|
| + DECLARE_INSTRUCTION_FACTORY_P2(HCompareObjectEqAndBranch, HValue*, HValue*);
|
| +
|
| HValue* left() { return OperandAt(0); }
|
| HValue* right() { return OperandAt(1); }
|
|
|
| @@ -4420,7 +4654,7 @@ class HTypeofIsAndBranch: public HUnaryControlInstruction {
|
| class HInstanceOf: public HBinaryOperation {
|
| public:
|
| HInstanceOf(HValue* context, HValue* left, HValue* right)
|
| - : HBinaryOperation(context, left, right) {
|
| + : HBinaryOperation(context, left, right, HType::Boolean()) {
|
| set_representation(Representation::Tagged());
|
| SetAllSideEffects();
|
| }
|
| @@ -4429,8 +4663,6 @@ class HInstanceOf: public HBinaryOperation {
|
| return Representation::Tagged();
|
| }
|
|
|
| - virtual HType CalculateInferredType();
|
| -
|
| virtual void PrintDataTo(StringStream* stream);
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(InstanceOf)
|
| @@ -4442,7 +4674,7 @@ class HInstanceOfKnownGlobal: public HTemplateInstruction<2> {
|
| HInstanceOfKnownGlobal(HValue* context,
|
| HValue* left,
|
| Handle<JSFunction> right)
|
| - : function_(right) {
|
| + : HTemplateInstruction<2>(HType::Boolean()), function_(right) {
|
| SetOperandAt(0, context);
|
| SetOperandAt(1, left);
|
| set_representation(Representation::Tagged());
|
| @@ -4457,8 +4689,6 @@ class HInstanceOfKnownGlobal: public HTemplateInstruction<2> {
|
| return Representation::Tagged();
|
| }
|
|
|
| - virtual HType CalculateInferredType();
|
| -
|
| DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal)
|
|
|
| private:
|
| @@ -4488,7 +4718,10 @@ class HInstanceSize: public HTemplateInstruction<1> {
|
|
|
| class HPower: public HTemplateInstruction<2> {
|
| public:
|
| - static HInstruction* New(Zone* zone, HValue* left, HValue* right);
|
| + static HInstruction* New(Zone* zone,
|
| + HValue* context,
|
| + HValue* left,
|
| + HValue* right);
|
|
|
| HValue* left() { return OperandAt(0); }
|
| HValue* right() const { return OperandAt(1); }
|
| @@ -4557,8 +4790,6 @@ class HAdd: public HArithmeticBinaryOperation {
|
|
|
| virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
|
|
|
| - virtual HType CalculateInferredType();
|
| -
|
| virtual HValue* Canonicalize();
|
|
|
| virtual bool TryDecompose(DecompositionResult* decomposition) {
|
| @@ -4825,8 +5056,8 @@ class HMathMinMax: public HArithmeticBinaryOperation {
|
| class HBitwise: public HBitwiseBinaryOperation {
|
| public:
|
| static HInstruction* New(Zone* zone,
|
| - Token::Value op,
|
| HValue* context,
|
| + Token::Value op,
|
| HValue* left,
|
| HValue* right);
|
|
|
| @@ -4848,8 +5079,12 @@ class HBitwise: public HBitwiseBinaryOperation {
|
| virtual Range* InferRange(Zone* zone);
|
|
|
| private:
|
| - HBitwise(Token::Value op, HValue* context, HValue* left, HValue* right)
|
| - : HBitwiseBinaryOperation(context, left, right), op_(op) {
|
| + HBitwise(HValue* context,
|
| + Token::Value op,
|
| + HValue* left,
|
| + HValue* right)
|
| + : HBitwiseBinaryOperation(context, left, right, HType::TaggedNumber()),
|
| + op_(op) {
|
| ASSERT(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR);
|
| // BIT_AND with a smi-range positive value will always unset the
|
| // entire sign-extension of the smi-sign.
|
| @@ -5010,10 +5245,7 @@ class HRor: public HBitwiseBinaryOperation {
|
|
|
| class HOsrEntry: public HTemplateInstruction<0> {
|
| public:
|
| - explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
|
| - SetGVNFlag(kChangesOsrEntries);
|
| - SetGVNFlag(kChangesNewSpacePromotion);
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P1(HOsrEntry, BailoutId);
|
|
|
| BailoutId ast_id() const { return ast_id_; }
|
|
|
| @@ -5024,6 +5256,11 @@ class HOsrEntry: public HTemplateInstruction<0> {
|
| DECLARE_CONCRETE_INSTRUCTION(OsrEntry)
|
|
|
| private:
|
| + explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
|
| + SetGVNFlag(kChangesOsrEntries);
|
| + SetGVNFlag(kChangesNewSpacePromotion);
|
| + }
|
| +
|
| BailoutId ast_id_;
|
| };
|
|
|
| @@ -5035,6 +5272,23 @@ class HParameter: public HTemplateInstruction<0> {
|
| REGISTER_PARAMETER
|
| };
|
|
|
| + DECLARE_INSTRUCTION_FACTORY_P1(HParameter, unsigned);
|
| + DECLARE_INSTRUCTION_FACTORY_P2(HParameter, unsigned, ParameterKind);
|
| + DECLARE_INSTRUCTION_FACTORY_P3(HParameter, unsigned, ParameterKind,
|
| + Representation);
|
| +
|
| + unsigned index() const { return index_; }
|
| + ParameterKind kind() const { return kind_; }
|
| +
|
| + virtual void PrintDataTo(StringStream* stream);
|
| +
|
| + virtual Representation RequiredInputRepresentation(int index) {
|
| + return Representation::None();
|
| + }
|
| +
|
| + DECLARE_CONCRETE_INSTRUCTION(Parameter)
|
| +
|
| + private:
|
| explicit HParameter(unsigned index,
|
| ParameterKind kind = STACK_PARAMETER)
|
| : index_(index),
|
| @@ -5050,18 +5304,6 @@ class HParameter: public HTemplateInstruction<0> {
|
| set_representation(r);
|
| }
|
|
|
| - 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_;
|
| };
|
| @@ -5102,10 +5344,7 @@ class HCallStub: public HUnaryCall {
|
|
|
| class HUnknownOSRValue: public HTemplateInstruction<0> {
|
| public:
|
| - HUnknownOSRValue()
|
| - : incoming_value_(NULL) {
|
| - set_representation(Representation::Tagged());
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P0(HUnknownOSRValue)
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| return Representation::None();
|
| @@ -5127,6 +5366,11 @@ class HUnknownOSRValue: public HTemplateInstruction<0> {
|
| DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
|
|
|
| private:
|
| + HUnknownOSRValue()
|
| + : incoming_value_(NULL) {
|
| + set_representation(Representation::Tagged());
|
| + }
|
| +
|
| HPhi* incoming_value_;
|
| };
|
|
|
| @@ -5209,41 +5453,19 @@ class HLoadGlobalGeneric: public HTemplateInstruction<2> {
|
|
|
| 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,
|
| - PREFILL_WITH_FILLER = 1 << 4
|
| - };
|
| -
|
| - HAllocate(HValue* context, HValue* size, HType type, Flags flags)
|
| - : flags_(flags) {
|
| - SetOperandAt(0, context);
|
| - SetOperandAt(1, size);
|
| - set_type(type);
|
| - set_representation(Representation::Tagged());
|
| - SetFlag(kTrackSideEffectDominators);
|
| - SetGVNFlag(kChangesNewSpacePromotion);
|
| - SetGVNFlag(kDependsOnNewSpacePromotion);
|
| + static HAllocate* New(Zone* zone,
|
| + HValue* context,
|
| + HValue* size,
|
| + HType type,
|
| + PretenureFlag pretenure_flag,
|
| + InstanceType instance_type) {
|
| + return new(zone) HAllocate(context, size, type, pretenure_flag,
|
| + instance_type);
|
| }
|
|
|
| // Maximum instance size for which allocations will be inlined.
|
| static const int kMaxInlineSize = 64 * kPointerSize;
|
|
|
| - static Flags DefaultFlags() {
|
| - return CAN_ALLOCATE_IN_NEW_SPACE;
|
| - }
|
| -
|
| - static Flags DefaultFlags(ElementsKind kind) {
|
| - Flags flags = CAN_ALLOCATE_IN_NEW_SPACE;
|
| - if (IsFastDoubleElementsKind(kind)) {
|
| - flags = static_cast<HAllocate::Flags>(
|
| - flags | HAllocate::ALLOCATE_DOUBLE_ALIGNED);
|
| - }
|
| - return flags;
|
| - }
|
| -
|
| HValue* context() { return OperandAt(0); }
|
| HValue* size() { return OperandAt(1); }
|
|
|
| @@ -5263,25 +5485,16 @@ class HAllocate: public HTemplateInstruction<2> {
|
| known_initial_map_ = known_initial_map;
|
| }
|
|
|
| - bool CanAllocateInNewSpace() const {
|
| - return (flags_ & CAN_ALLOCATE_IN_NEW_SPACE) != 0;
|
| - }
|
| -
|
| - bool CanAllocateInOldDataSpace() const {
|
| - return (flags_ & CAN_ALLOCATE_IN_OLD_DATA_SPACE) != 0;
|
| + bool IsNewSpaceAllocation() const {
|
| + return (flags_ & ALLOCATE_IN_NEW_SPACE) != 0;
|
| }
|
|
|
| - bool CanAllocateInOldPointerSpace() const {
|
| - return (flags_ & CAN_ALLOCATE_IN_OLD_POINTER_SPACE) != 0;
|
| + bool IsOldDataSpaceAllocation() const {
|
| + return (flags_ & ALLOCATE_IN_OLD_DATA_SPACE) != 0;
|
| }
|
|
|
| - bool CanAllocateInOldSpace() const {
|
| - return CanAllocateInOldDataSpace() ||
|
| - CanAllocateInOldPointerSpace();
|
| - }
|
| -
|
| - bool GuaranteedInNewSpace() const {
|
| - return CanAllocateInNewSpace() && !CanAllocateInOldSpace();
|
| + bool IsOldPointerSpaceAllocation() const {
|
| + return (flags_ & ALLOCATE_IN_OLD_POINTER_SPACE) != 0;
|
| }
|
|
|
| bool MustAllocateDoubleAligned() const {
|
| @@ -5292,8 +5505,12 @@ class HAllocate: public HTemplateInstruction<2> {
|
| return (flags_ & PREFILL_WITH_FILLER) != 0;
|
| }
|
|
|
| - void SetFlags(Flags flags) {
|
| - flags_ = static_cast<HAllocate::Flags>(flags_ | flags);
|
| + void MakePrefillWithFiller() {
|
| + flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER);
|
| + }
|
| +
|
| + void MakeDoubleAligned() {
|
| + flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED);
|
| }
|
|
|
| void UpdateSize(HValue* size) {
|
| @@ -5308,6 +5525,36 @@ class HAllocate: public HTemplateInstruction<2> {
|
| DECLARE_CONCRETE_INSTRUCTION(Allocate)
|
|
|
| private:
|
| + enum Flags {
|
| + ALLOCATE_IN_NEW_SPACE = 1 << 0,
|
| + ALLOCATE_IN_OLD_DATA_SPACE = 1 << 1,
|
| + ALLOCATE_IN_OLD_POINTER_SPACE = 1 << 2,
|
| + ALLOCATE_DOUBLE_ALIGNED = 1 << 3,
|
| + PREFILL_WITH_FILLER = 1 << 4
|
| + };
|
| +
|
| + HAllocate(HValue* context,
|
| + HValue* size,
|
| + HType type,
|
| + PretenureFlag pretenure_flag,
|
| + InstanceType instance_type)
|
| + : HTemplateInstruction<2>(type) {
|
| + SetOperandAt(0, context);
|
| + SetOperandAt(1, size);
|
| + set_representation(Representation::Tagged());
|
| + SetFlag(kTrackSideEffectDominators);
|
| + SetGVNFlag(kChangesNewSpacePromotion);
|
| + SetGVNFlag(kDependsOnNewSpacePromotion);
|
| + flags_ = pretenure_flag == TENURED
|
| + ? (Heap::TargetSpaceId(instance_type) == OLD_POINTER_SPACE
|
| + ? ALLOCATE_IN_OLD_POINTER_SPACE : ALLOCATE_IN_OLD_DATA_SPACE)
|
| + : ALLOCATE_IN_NEW_SPACE;
|
| + if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
|
| + flags_ = static_cast<HAllocate::Flags>(flags_ |
|
| + ALLOCATE_DOUBLE_ALIGNED);
|
| + }
|
| + }
|
| +
|
| Flags flags_;
|
| Handle<Map> known_initial_map_;
|
| };
|
| @@ -5315,12 +5562,12 @@ class HAllocate: public HTemplateInstruction<2> {
|
|
|
| class HInnerAllocatedObject: public HTemplateInstruction<1> {
|
| public:
|
| - HInnerAllocatedObject(HValue* value, int offset, HType type = HType::Tagged())
|
| - : offset_(offset) {
|
| - ASSERT(value->IsAllocate());
|
| - SetOperandAt(0, value);
|
| - set_type(type);
|
| - set_representation(Representation::Tagged());
|
| + static HInnerAllocatedObject* New(Zone* zone,
|
| + HValue* context,
|
| + HValue* value,
|
| + int offset,
|
| + HType type = HType::Tagged()) {
|
| + return new(zone) HInnerAllocatedObject(value, offset, type);
|
| }
|
|
|
| HValue* base_object() { return OperandAt(0); }
|
| @@ -5335,6 +5582,14 @@ class HInnerAllocatedObject: public HTemplateInstruction<1> {
|
| DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject)
|
|
|
| private:
|
| + HInnerAllocatedObject(HValue* value, int offset, HType type = HType::Tagged())
|
| + : HTemplateInstruction<1>(type), offset_(offset) {
|
| + ASSERT(value->IsAllocate());
|
| + SetOperandAt(0, value);
|
| + set_type(type);
|
| + set_representation(Representation::Tagged());
|
| + }
|
| +
|
| int offset_;
|
| };
|
|
|
| @@ -5356,9 +5611,14 @@ inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
|
| if (object->IsConstant() && HConstant::cast(object)->IsCell()) {
|
| return false;
|
| }
|
| + if (object->IsConstant() &&
|
| + HConstant::cast(object)->HasExternalReferenceValue()) {
|
| + // Stores to external references require no write barriers
|
| + return false;
|
| + }
|
| if (object != new_space_dominator) return true;
|
| if (object->IsAllocate()) {
|
| - return !HAllocate::cast(object)->GuaranteedInNewSpace();
|
| + return !HAllocate::cast(object)->IsNewSpaceAllocation();
|
| }
|
| return true;
|
| }
|
| @@ -5366,14 +5626,8 @@ inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
|
|
|
| class HStoreGlobalCell: public HUnaryOperation {
|
| public:
|
| - HStoreGlobalCell(HValue* value,
|
| - Handle<PropertyCell> cell,
|
| - PropertyDetails details)
|
| - : HUnaryOperation(value),
|
| - cell_(cell),
|
| - details_(details) {
|
| - SetGVNFlag(kChangesGlobalVars);
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P3(HStoreGlobalCell, HValue*,
|
| + Handle<PropertyCell>, PropertyDetails);
|
|
|
| Handle<PropertyCell> cell() const { return cell_; }
|
| bool RequiresHoleCheck() {
|
| @@ -5391,6 +5645,15 @@ class HStoreGlobalCell: public HUnaryOperation {
|
| DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell)
|
|
|
| private:
|
| + HStoreGlobalCell(HValue* value,
|
| + Handle<PropertyCell> cell,
|
| + PropertyDetails details)
|
| + : HUnaryOperation(value),
|
| + cell_(cell),
|
| + details_(details) {
|
| + SetGVNFlag(kChangesGlobalVars);
|
| + }
|
| +
|
| Handle<PropertyCell> cell_;
|
| PropertyDetails details_;
|
| };
|
| @@ -5398,18 +5661,14 @@ class HStoreGlobalCell: public HUnaryOperation {
|
|
|
| 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();
|
| + inline static HStoreGlobalGeneric* New(Zone* zone,
|
| + HValue* context,
|
| + HValue* global_object,
|
| + Handle<Object> name,
|
| + HValue* value,
|
| + StrictModeFlag strict_mode_flag) {
|
| + return new(zone) HStoreGlobalGeneric(context, global_object,
|
| + name, value, strict_mode_flag);
|
| }
|
|
|
| HValue* context() { return OperandAt(0); }
|
| @@ -5427,6 +5686,20 @@ class HStoreGlobalGeneric: public HTemplateInstruction<3> {
|
| DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric)
|
|
|
| private:
|
| + 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();
|
| + }
|
| +
|
| Handle<Object> name_;
|
| StrictModeFlag strict_mode_flag_;
|
| };
|
| @@ -5514,12 +5787,8 @@ class HStoreContextSlot: public HTemplateInstruction<2> {
|
| 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);
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P4(HStoreContextSlot, HValue*, int,
|
| + Mode, HValue*);
|
|
|
| HValue* context() { return OperandAt(0); }
|
| HValue* value() { return OperandAt(1); }
|
| @@ -5547,6 +5816,13 @@ class HStoreContextSlot: public HTemplateInstruction<2> {
|
| DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
|
|
|
| private:
|
| + HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
|
| + : slot_index_(slot_index), mode_(mode) {
|
| + SetOperandAt(0, context);
|
| + SetOperandAt(1, value);
|
| + SetGVNFlag(kChangesContextSlots);
|
| + }
|
| +
|
| int slot_index_;
|
| Mode mode_;
|
| };
|
| @@ -5557,7 +5833,15 @@ class HStoreContextSlot: public HTemplateInstruction<2> {
|
| class HObjectAccess {
|
| public:
|
| inline bool IsInobject() const {
|
| - return portion() != kBackingStore;
|
| + return portion() != kBackingStore && portion() != kExternalMemory;
|
| + }
|
| +
|
| + inline bool IsExternalMemory() const {
|
| + return portion() == kExternalMemory;
|
| + }
|
| +
|
| + inline bool IsStringLength() const {
|
| + return portion() == kStringLengths;
|
| }
|
|
|
| inline int offset() const {
|
| @@ -5587,9 +5871,11 @@ class HObjectAccess {
|
|
|
| static HObjectAccess ForArrayLength(ElementsKind elements_kind) {
|
| return HObjectAccess(
|
| - kArrayLengths, JSArray::kLengthOffset,
|
| - IsFastElementsKind(elements_kind) && FLAG_track_fields ?
|
| - Representation::Smi() : Representation::Tagged());
|
| + kArrayLengths,
|
| + JSArray::kLengthOffset,
|
| + IsFastElementsKind(elements_kind) &&
|
| + FLAG_track_fields
|
| + ? Representation::Smi() : Representation::Tagged());
|
| }
|
|
|
| static HObjectAccess ForAllocationSiteTransitionInfo() {
|
| @@ -5600,11 +5886,23 @@ class HObjectAccess {
|
| return HObjectAccess(kInobject, AllocationSite::kWeakNextOffset);
|
| }
|
|
|
| + static HObjectAccess ForAllocationSiteList() {
|
| + return HObjectAccess(kExternalMemory, 0, Representation::Tagged());
|
| + }
|
| +
|
| static HObjectAccess ForFixedArrayLength() {
|
| return HObjectAccess(
|
| - kArrayLengths, FixedArray::kLengthOffset,
|
| - FLAG_track_fields ?
|
| - Representation::Smi() : Representation::Tagged());
|
| + kArrayLengths,
|
| + FixedArray::kLengthOffset,
|
| + FLAG_track_fields ? Representation::Smi() : Representation::Tagged());
|
| + }
|
| +
|
| + static HObjectAccess ForStringLength() {
|
| + STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
|
| + return HObjectAccess(
|
| + kStringLengths,
|
| + String::kLengthOffset,
|
| + FLAG_track_fields ? Representation::Smi() : Representation::Tagged());
|
| }
|
|
|
| static HObjectAccess ForPropertiesPointer() {
|
| @@ -5631,6 +5929,10 @@ class HObjectAccess {
|
| return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset);
|
| }
|
|
|
| + static HObjectAccess ForCounter() {
|
| + return HObjectAccess(kExternalMemory, 0, Representation::Integer32());
|
| + }
|
| +
|
| // Create an access to an offset in a fixed array header.
|
| static HObjectAccess ForFixedArrayHeader(int offset);
|
|
|
| @@ -5666,10 +5968,12 @@ class HObjectAccess {
|
| enum Portion {
|
| kMaps, // map of an object
|
| kArrayLengths, // the length of an array
|
| + kStringLengths, // the length of a string
|
| kElementsPointer, // elements pointer
|
| kBackingStore, // some field in the backing store
|
| kDouble, // some double field
|
| - kInobject // some other in-object field
|
| + kInobject, // some other in-object field
|
| + kExternalMemory // some field in external memory
|
| };
|
|
|
| HObjectAccess(Portion portion, int offset,
|
| @@ -5701,40 +6005,44 @@ class HObjectAccess {
|
| };
|
|
|
|
|
| -class HLinkObjectInList: public HUnaryOperation {
|
| +class HLoadNamedField: public HTemplateInstruction<2> {
|
| public:
|
| - // There needs to be a mapping from every KnownList to an external reference
|
| - enum KnownList {
|
| - ALLOCATION_SITE_LIST
|
| - };
|
| + DECLARE_INSTRUCTION_FACTORY_P2(HLoadNamedField, HValue*, HObjectAccess);
|
| + DECLARE_INSTRUCTION_FACTORY_P3(HLoadNamedField, HValue*, HObjectAccess,
|
| + HValue*);
|
|
|
| - HLinkObjectInList(HValue* object, HObjectAccess store_field,
|
| - KnownList known_list)
|
| - : HUnaryOperation(object),
|
| - store_field_(store_field),
|
| - known_list_(known_list) {
|
| - set_representation(Representation::Tagged());
|
| + HValue* object() { return OperandAt(0); }
|
| + HValue* typecheck() {
|
| + ASSERT(HasTypeCheck());
|
| + return OperandAt(1);
|
| }
|
|
|
| - HObjectAccess store_field() const { return store_field_; }
|
| - KnownList known_list() const { return known_list_; }
|
| + bool HasTypeCheck() const { return OperandAt(0) != OperandAt(1); }
|
| + HObjectAccess access() const { return access_; }
|
| + Representation field_representation() const {
|
| + return access_.representation();
|
| + }
|
|
|
| + virtual bool HasEscapingOperandAt(int index) { return false; }
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| + if (index == 0 && access().IsExternalMemory()) {
|
| + // object must be external in case of external memory access
|
| + return Representation::External();
|
| + }
|
| return Representation::Tagged();
|
| }
|
| -
|
| + virtual Range* InferRange(Zone* zone);
|
| virtual void PrintDataTo(StringStream* stream);
|
|
|
| - DECLARE_CONCRETE_INSTRUCTION(LinkObjectInList)
|
| -
|
| - private:
|
| - HObjectAccess store_field_;
|
| - KnownList known_list_;
|
| -};
|
| + DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
|
|
|
| + protected:
|
| + virtual bool DataEquals(HValue* other) {
|
| + HLoadNamedField* b = HLoadNamedField::cast(other);
|
| + return access_.Equals(b->access_);
|
| + }
|
|
|
| -class HLoadNamedField: public HTemplateInstruction<2> {
|
| - public:
|
| + private:
|
| HLoadNamedField(HValue* object,
|
| HObjectAccess access,
|
| HValue* typecheck = NULL)
|
| @@ -5747,7 +6055,9 @@ class HLoadNamedField: public HTemplateInstruction<2> {
|
| if (representation.IsSmi()) {
|
| set_type(HType::Smi());
|
| set_representation(representation);
|
| - } else if (representation.IsDouble()) {
|
| + } else if (representation.IsDouble() ||
|
| + representation.IsExternal() ||
|
| + representation.IsInteger32()) {
|
| set_representation(representation);
|
| } else if (FLAG_track_heap_object_fields &&
|
| representation.IsHeapObject()) {
|
| @@ -5759,33 +6069,6 @@ class HLoadNamedField: public HTemplateInstruction<2> {
|
| access.SetGVNFlags(this, false);
|
| }
|
|
|
| - HValue* object() { return OperandAt(0); }
|
| - HValue* typecheck() {
|
| - ASSERT(HasTypeCheck());
|
| - return OperandAt(1);
|
| - }
|
| -
|
| - bool HasTypeCheck() const { return OperandAt(0) != OperandAt(1); }
|
| - HObjectAccess access() const { return access_; }
|
| - Representation field_representation() const {
|
| - return access_.representation();
|
| - }
|
| -
|
| - virtual bool HasEscapingOperandAt(int index) { return false; }
|
| - 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 access_.Equals(b->access_);
|
| - }
|
| -
|
| - private:
|
| virtual bool IsDeletable() const { return true; }
|
|
|
| HObjectAccess access_;
|
| @@ -5904,55 +6187,10 @@ enum LoadKeyedHoleMode {
|
| 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) &&
|
| - (!IsHoleyElementsKind(elements_kind) ||
|
| - mode == NEVER_RETURN_HOLE)) {
|
| - set_type(HType::Smi());
|
| - set_representation(Representation::Smi());
|
| - } else {
|
| - 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);
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P4(HLoadKeyed, HValue*, HValue*, HValue*,
|
| + ElementsKind);
|
| + DECLARE_INSTRUCTION_FACTORY_P5(HLoadKeyed, HValue*, HValue*, HValue*,
|
| + ElementsKind, LoadKeyedHoleMode);
|
|
|
| bool is_external() const {
|
| return IsExternalArrayElementsKind(elements_kind());
|
| @@ -6021,6 +6259,56 @@ class HLoadKeyed
|
| }
|
|
|
| private:
|
| + 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) &&
|
| + (!IsHoleyElementsKind(elements_kind) ||
|
| + mode == NEVER_RETURN_HOLE)) {
|
| + set_type(HType::Smi());
|
| + set_representation(Representation::Smi());
|
| + } else {
|
| + 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(kDependsOnExternalMemory);
|
| + // Native code could change the specialized array.
|
| + SetGVNFlag(kDependsOnCalls);
|
| + }
|
| +
|
| + SetFlag(kUseGVN);
|
| + }
|
| +
|
| virtual bool IsDeletable() const {
|
| return !RequiresHoleCheck();
|
| }
|
| @@ -6086,26 +6374,20 @@ class HLoadKeyedGeneric: public HTemplateInstruction<3> {
|
|
|
| class HStoreNamedField: public HTemplateInstruction<2> {
|
| public:
|
| - HStoreNamedField(HValue* obj,
|
| - HObjectAccess access,
|
| - HValue* val)
|
| - : access_(access),
|
| - transition_(),
|
| - transition_unique_id_(),
|
| - new_space_dominator_(NULL),
|
| - write_barrier_mode_(UPDATE_WRITE_BARRIER) {
|
| - SetOperandAt(0, obj);
|
| - SetOperandAt(1, val);
|
| - access.SetGVNFlags(this, true);
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*,
|
| + HObjectAccess, HValue*);
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
|
|
|
| virtual bool HasEscapingOperandAt(int index) { return index == 1; }
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| - if (index == 1 && field_representation().IsDouble()) {
|
| - return field_representation();
|
| - } else if (index == 1 && field_representation().IsSmi()) {
|
| + if (index == 0 && access().IsExternalMemory()) {
|
| + // object must be external in case of external memory access
|
| + return Representation::External();
|
| + } else if (index == 1 &&
|
| + (field_representation().IsDouble() ||
|
| + field_representation().IsSmi() ||
|
| + field_representation().IsInteger32())) {
|
| return field_representation();
|
| }
|
| return Representation::Tagged();
|
| @@ -6143,6 +6425,8 @@ class HStoreNamedField: public HTemplateInstruction<2> {
|
| if (IsSkipWriteBarrier()) return false;
|
| if (field_representation().IsDouble()) return false;
|
| if (field_representation().IsSmi()) return false;
|
| + if (field_representation().IsInteger32()) return false;
|
| + if (field_representation().IsExternal()) return false;
|
| return StoringValueNeedsWriteBarrier(value()) &&
|
| ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
|
| }
|
| @@ -6161,6 +6445,19 @@ class HStoreNamedField: public HTemplateInstruction<2> {
|
| }
|
|
|
| private:
|
| + HStoreNamedField(HValue* obj,
|
| + HObjectAccess access,
|
| + HValue* val)
|
| + : access_(access),
|
| + transition_(),
|
| + transition_unique_id_(),
|
| + new_space_dominator_(NULL),
|
| + write_barrier_mode_(UPDATE_WRITE_BARRIER) {
|
| + SetOperandAt(0, obj);
|
| + SetOperandAt(1, val);
|
| + access.SetGVNFlags(this, true);
|
| + }
|
| +
|
| HObjectAccess access_;
|
| Handle<Map> transition_;
|
| UniqueValueId transition_unique_id_;
|
| @@ -6207,38 +6504,8 @@ class HStoreNamedGeneric: public HTemplateInstruction<3> {
|
| 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),
|
| - is_uninitialized_(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);
|
| - SetFlag(kAllowUndefinedAsNaN);
|
| - } else if (IsFastDoubleElementsKind(elements_kind)) {
|
| - SetGVNFlag(kChangesDoubleArrayElements);
|
| - } else if (IsFastSmiElementsKind(elements_kind)) {
|
| - SetGVNFlag(kChangesArrayElements);
|
| - } 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);
|
| - }
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P4(HStoreKeyed, HValue*, HValue*, HValue*,
|
| + ElementsKind);
|
|
|
| virtual bool HasEscapingOperandAt(int index) { return index != 0; }
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| @@ -6335,6 +6602,39 @@ class HStoreKeyed
|
| DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)
|
|
|
| private:
|
| + HStoreKeyed(HValue* obj, HValue* key, HValue* val,
|
| + ElementsKind elements_kind)
|
| + : elements_kind_(elements_kind),
|
| + index_offset_(0),
|
| + is_dehoisted_(false),
|
| + is_uninitialized_(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(kChangesExternalMemory);
|
| + SetFlag(kAllowUndefinedAsNaN);
|
| + } else if (IsFastDoubleElementsKind(elements_kind)) {
|
| + SetGVNFlag(kChangesDoubleArrayElements);
|
| + } else if (IsFastSmiElementsKind(elements_kind)) {
|
| + SetGVNFlag(kChangesArrayElements);
|
| + } 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);
|
| + }
|
| + }
|
| +
|
| ElementsKind elements_kind_;
|
| uint32_t index_offset_;
|
| bool is_dehoisted_ : 1;
|
| @@ -6380,29 +6680,13 @@ class HStoreKeyedGeneric: public HTemplateInstruction<4> {
|
|
|
| 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),
|
| - original_map_unique_id_(),
|
| - transitioned_map_unique_id_(),
|
| - 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());
|
| + inline static HTransitionElementsKind* New(Zone* zone,
|
| + HValue* context,
|
| + HValue* object,
|
| + Handle<Map> original_map,
|
| + Handle<Map> transitioned_map) {
|
| + return new(zone) HTransitionElementsKind(context, object,
|
| + original_map, transitioned_map);
|
| }
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| @@ -6433,6 +6717,31 @@ class HTransitionElementsKind: public HTemplateInstruction<2> {
|
| }
|
|
|
| private:
|
| + HTransitionElementsKind(HValue* context,
|
| + HValue* object,
|
| + Handle<Map> original_map,
|
| + Handle<Map> transitioned_map)
|
| + : original_map_(original_map),
|
| + transitioned_map_(transitioned_map),
|
| + original_map_unique_id_(),
|
| + transitioned_map_unique_id_(),
|
| + 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());
|
| + }
|
| +
|
| Handle<Map> original_map_;
|
| Handle<Map> transitioned_map_;
|
| UniqueValueId original_map_unique_id_;
|
| @@ -6456,10 +6765,6 @@ class HStringAdd: public HBinaryOperation {
|
| return Representation::Tagged();
|
| }
|
|
|
| - virtual HType CalculateInferredType() {
|
| - return HType::String();
|
| - }
|
| -
|
| DECLARE_CONCRETE_INSTRUCTION(StringAdd)
|
|
|
| protected:
|
| @@ -6467,15 +6772,16 @@ class HStringAdd: public HBinaryOperation {
|
|
|
| private:
|
| HStringAdd(HValue* context, HValue* left, HValue* right, StringAddFlags flags)
|
| - : HBinaryOperation(context, left, right), flags_(flags) {
|
| + : HBinaryOperation(context, left, right, HType::String()), flags_(flags) {
|
| 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; }
|
| + // No side-effects except possible allocation.
|
| + // NOTE: this instruction _does not_ call ToString() on its inputs.
|
| + virtual bool IsDeletable() const { return true; }
|
|
|
| const StringAddFlags flags_;
|
| };
|
| @@ -6483,14 +6789,11 @@ class HStringAdd: public HBinaryOperation {
|
|
|
| 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);
|
| + static HStringCharCodeAt* New(Zone* zone,
|
| + HValue* context,
|
| + HValue* string,
|
| + HValue* index) {
|
| + return new(zone) HStringCharCodeAt(context, string, index);
|
| }
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| @@ -6500,9 +6803,9 @@ class HStringCharCodeAt: public HTemplateInstruction<3> {
|
| : Representation::Tagged();
|
| }
|
|
|
| - HValue* context() { return OperandAt(0); }
|
| - HValue* string() { return OperandAt(1); }
|
| - HValue* index() { return OperandAt(2); }
|
| + HValue* context() const { return OperandAt(0); }
|
| + HValue* string() const { return OperandAt(1); }
|
| + HValue* index() const { return OperandAt(2); }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
|
|
|
| @@ -6513,9 +6816,19 @@ class HStringCharCodeAt: public HTemplateInstruction<3> {
|
| 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; }
|
| + private:
|
| + 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);
|
| + }
|
| +
|
| + // No side effects: runtime function assumes string + number inputs.
|
| + virtual bool IsDeletable() const { return true; }
|
| };
|
|
|
|
|
| @@ -6530,17 +6843,17 @@ class HStringCharFromCode: public HTemplateInstruction<2> {
|
| ? Representation::Tagged()
|
| : Representation::Integer32();
|
| }
|
| - virtual HType CalculateInferredType();
|
|
|
| - HValue* context() { return OperandAt(0); }
|
| - HValue* value() { return OperandAt(1); }
|
| + HValue* context() const { return OperandAt(0); }
|
| + HValue* value() const { return OperandAt(1); }
|
|
|
| virtual bool DataEquals(HValue* other) { return true; }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
|
|
|
| private:
|
| - HStringCharFromCode(HValue* context, HValue* char_code) {
|
| + HStringCharFromCode(HValue* context, HValue* char_code)
|
| + : HTemplateInstruction<2>(HType::String()) {
|
| SetOperandAt(0, context);
|
| SetOperandAt(1, char_code);
|
| set_representation(Representation::Tagged());
|
| @@ -6548,41 +6861,9 @@ class HStringCharFromCode: public HTemplateInstruction<2> {
|
| 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 !value()->ToNumberCanBeObserved();
|
| }
|
| -
|
| - virtual bool IsDeletable() const { return true; }
|
| };
|
|
|
|
|
| @@ -6628,6 +6909,7 @@ class HRegExpLiteral: public HMaterializedLiteral<1> {
|
| flags_(flags) {
|
| SetOperandAt(0, context);
|
| SetAllSideEffects();
|
| + set_type(HType::JSObject());
|
| }
|
|
|
| HValue* context() { return OperandAt(0); }
|
| @@ -6638,7 +6920,6 @@ class HRegExpLiteral: public HMaterializedLiteral<1> {
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| return Representation::Tagged();
|
| }
|
| - virtual HType CalculateInferredType();
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral)
|
|
|
| @@ -6654,7 +6935,8 @@ class HFunctionLiteral: public HTemplateInstruction<1> {
|
| HFunctionLiteral(HValue* context,
|
| Handle<SharedFunctionInfo> shared,
|
| bool pretenure)
|
| - : shared_info_(shared),
|
| + : HTemplateInstruction<1>(HType::JSObject()),
|
| + shared_info_(shared),
|
| pretenure_(pretenure),
|
| has_no_literals_(shared->num_literals() == 0),
|
| is_generator_(shared->is_generator()),
|
| @@ -6669,7 +6951,6 @@ class HFunctionLiteral: public HTemplateInstruction<1> {
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| return Representation::Tagged();
|
| }
|
| - virtual HType CalculateInferredType();
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral)
|
|
|
| @@ -6716,9 +6997,7 @@ class HTypeof: public HTemplateInstruction<2> {
|
|
|
| class HTrapAllocationMemento : public HTemplateInstruction<1> {
|
| public:
|
| - explicit HTrapAllocationMemento(HValue* obj) {
|
| - SetOperandAt(0, obj);
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P1(HTrapAllocationMemento, HValue*);
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| return Representation::Tagged();
|
| @@ -6727,11 +7006,25 @@ class HTrapAllocationMemento : public HTemplateInstruction<1> {
|
| HValue* object() { return OperandAt(0); }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento)
|
| +
|
| + private:
|
| + explicit HTrapAllocationMemento(HValue* obj) {
|
| + SetOperandAt(0, obj);
|
| + }
|
| };
|
|
|
|
|
| class HToFastProperties: public HUnaryOperation {
|
| public:
|
| + DECLARE_INSTRUCTION_FACTORY_P1(HToFastProperties, HValue*);
|
| +
|
| + virtual Representation RequiredInputRepresentation(int index) {
|
| + return Representation::Tagged();
|
| + }
|
| +
|
| + DECLARE_CONCRETE_INSTRUCTION(ToFastProperties)
|
| +
|
| + private:
|
| 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
|
| @@ -6745,13 +7038,6 @@ class HToFastProperties: public HUnaryOperation {
|
| set_representation(Representation::Tagged());
|
| }
|
|
|
| - virtual Representation RequiredInputRepresentation(int index) {
|
| - return Representation::Tagged();
|
| - }
|
| -
|
| - DECLARE_CONCRETE_INSTRUCTION(ToFastProperties)
|
| -
|
| - private:
|
| virtual bool IsDeletable() const { return true; }
|
| };
|
|
|
| @@ -6824,15 +7110,7 @@ class HSeqStringSetChar: public HTemplateInstruction<3> {
|
|
|
| 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);
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P2(HCheckMapValue, HValue*, HValue*);
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| return Representation::Tagged();
|
| @@ -6853,17 +7131,26 @@ class HCheckMapValue: public HTemplateInstruction<2> {
|
| virtual bool DataEquals(HValue* other) {
|
| return true;
|
| }
|
| +
|
| + private:
|
| + HCheckMapValue(HValue* value,
|
| + HValue* map) {
|
| + SetOperandAt(0, value);
|
| + SetOperandAt(1, map);
|
| + set_representation(Representation::Tagged());
|
| + SetFlag(kUseGVN);
|
| + SetGVNFlag(kDependsOnMaps);
|
| + SetGVNFlag(kDependsOnElementsKind);
|
| + }
|
| };
|
|
|
|
|
| class HForInPrepareMap : public HTemplateInstruction<2> {
|
| public:
|
| - HForInPrepareMap(HValue* context,
|
| - HValue* object) {
|
| - SetOperandAt(0, context);
|
| - SetOperandAt(1, object);
|
| - set_representation(Representation::Tagged());
|
| - SetAllSideEffects();
|
| + static HForInPrepareMap* New(Zone* zone,
|
| + HValue* context,
|
| + HValue* object) {
|
| + return new(zone) HForInPrepareMap(context, object);
|
| }
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| @@ -6880,18 +7167,21 @@ class HForInPrepareMap : public HTemplateInstruction<2> {
|
| }
|
|
|
| DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
|
| +
|
| + private:
|
| + HForInPrepareMap(HValue* context,
|
| + HValue* object) {
|
| + SetOperandAt(0, context);
|
| + SetOperandAt(1, object);
|
| + set_representation(Representation::Tagged());
|
| + SetAllSideEffects();
|
| + }
|
| };
|
|
|
|
|
| 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());
|
| - }
|
| + DECLARE_INSTRUCTION_FACTORY_P3(HForInCacheArray, HValue*, HValue*, int);
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| return Representation::Tagged();
|
| @@ -6918,6 +7208,14 @@ class HForInCacheArray : public HTemplateInstruction<2> {
|
| DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
|
|
|
| private:
|
| + HForInCacheArray(HValue* enumerable,
|
| + HValue* keys,
|
| + int idx) : idx_(idx) {
|
| + SetOperandAt(0, enumerable);
|
| + SetOperandAt(1, keys);
|
| + set_representation(Representation::Tagged());
|
| + }
|
| +
|
| int idx_;
|
| HForInCacheArray* index_cache_;
|
| };
|
|
|