summaryrefslogtreecommitdiff
path: root/deps/v8/src/hydrogen-instructions.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/hydrogen-instructions.h')
-rw-r--r--deps/v8/src/hydrogen-instructions.h1749
1 files changed, 1031 insertions, 718 deletions
diff --git a/deps/v8/src/hydrogen-instructions.h b/deps/v8/src/hydrogen-instructions.h
index da5cdeced4..4976f7b90c 100644
--- a/deps/v8/src/hydrogen-instructions.h
+++ b/deps/v8/src/hydrogen-instructions.h
@@ -46,6 +46,7 @@ namespace internal {
// Forward declarations.
class HBasicBlock;
+class HDiv;
class HEnvironment;
class HInferRepresentationPhase;
class HInstruction;
@@ -77,12 +78,9 @@ class LChunkBuilder;
V(BoundsCheck) \
V(BoundsCheckBaseIndexInformation) \
V(Branch) \
- V(CallConstantFunction) \
+ V(CallWithDescriptor) \
+ V(CallJSFunction) \
V(CallFunction) \
- V(CallGlobal) \
- V(CallKeyed) \
- V(CallKnownGlobal) \
- V(CallNamed) \
V(CallNew) \
V(CallNewArray) \
V(CallRuntime) \
@@ -100,6 +98,7 @@ class LChunkBuilder;
V(CompareNumericAndBranch) \
V(CompareHoleAndBranch) \
V(CompareGeneric) \
+ V(CompareMinusZeroAndBranch) \
V(CompareObjectEqAndBranch) \
V(CompareMap) \
V(Constant) \
@@ -110,7 +109,6 @@ class LChunkBuilder;
V(Deoptimize) \
V(Div) \
V(DummyUse) \
- V(ElementsKind) \
V(EnterInlined) \
V(EnvironmentMarker) \
V(ForceRepresentation) \
@@ -118,8 +116,6 @@ class LChunkBuilder;
V(ForInPrepareMap) \
V(FunctionLiteral) \
V(GetCachedArrayIndex) \
- V(GlobalObject) \
- V(GlobalReceiver) \
V(Goto) \
V(HasCachedArrayIndexAndBranch) \
V(HasInstanceTypeAndBranch) \
@@ -134,7 +130,6 @@ class LChunkBuilder;
V(IsUndetectableAndBranch) \
V(LeaveInlined) \
V(LoadContextSlot) \
- V(LoadExternalArrayPointer) \
V(LoadFieldByIndex) \
V(LoadFunctionPrototype) \
V(LoadGlobalCell) \
@@ -150,15 +145,14 @@ class LChunkBuilder;
V(Mod) \
V(Mul) \
V(OsrEntry) \
- V(OuterContext) \
V(Parameter) \
V(Power) \
V(PushArgument) \
- V(Random) \
V(RegExpLiteral) \
V(Return) \
V(Ror) \
V(Sar) \
+ V(SeqStringGetChar) \
V(SeqStringSetChar) \
V(Shl) \
V(Shr) \
@@ -167,7 +161,6 @@ class LChunkBuilder;
V(StoreCodeEntry) \
V(StoreContextSlot) \
V(StoreGlobalCell) \
- V(StoreGlobalGeneric) \
V(StoreKeyed) \
V(StoreKeyedGeneric) \
V(StoreNamedField) \
@@ -178,7 +171,6 @@ class LChunkBuilder;
V(StringCompareAndBranch) \
V(Sub) \
V(ThisFunction) \
- V(Throw) \
V(ToFastProperties) \
V(TransitionElementsKind) \
V(TrapAllocationMemento) \
@@ -187,7 +179,6 @@ class LChunkBuilder;
V(UnaryMathOperation) \
V(UnknownOSRValue) \
V(UseConst) \
- V(ValueOf) \
V(WrapReceiver)
#define GVN_TRACKED_FLAG_LIST(V) \
@@ -208,7 +199,9 @@ class LChunkBuilder;
V(GlobalVars) \
V(InobjectFields) \
V(OsrEntries) \
- V(ExternalMemory)
+ V(ExternalMemory) \
+ V(StringChars) \
+ V(TypedArrayElements)
#define DECLARE_ABSTRACT_INSTRUCTION(type) \
@@ -231,6 +224,9 @@ class LChunkBuilder;
}
+enum PropertyAccessType { LOAD, STORE };
+
+
class Range V8_FINAL : public ZoneObject {
public:
Range()
@@ -480,23 +476,28 @@ class HUseIterator V8_FINAL BASE_EMBEDDED {
};
-// There must be one corresponding kDepends flag for every kChanges flag and
-// the order of the kChanges flags must be exactly the same as of the kDepends
-// flags. All tracked flags should appear before untracked ones.
+// All tracked flags should appear before untracked ones.
enum GVNFlag {
// Declare global value numbering flags.
-#define DECLARE_FLAG(type) kChanges##type, kDependsOn##type,
+#define DECLARE_FLAG(Type) k##Type,
GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
#undef DECLARE_FLAG
- kAfterLastFlag,
- kLastFlag = kAfterLastFlag - 1,
-#define COUNT_FLAG(type) + 1
- kNumberOfTrackedSideEffects = 0 GVN_TRACKED_FLAG_LIST(COUNT_FLAG)
+#define COUNT_FLAG(Type) + 1
+ kNumberOfTrackedSideEffects = 0 GVN_TRACKED_FLAG_LIST(COUNT_FLAG),
+ kNumberOfUntrackedSideEffects = 0 GVN_UNTRACKED_FLAG_LIST(COUNT_FLAG),
#undef COUNT_FLAG
+ kNumberOfFlags = kNumberOfTrackedSideEffects + kNumberOfUntrackedSideEffects
};
+static inline GVNFlag GVNFlagFromInt(int i) {
+ ASSERT(i >= 0);
+ ASSERT(i < kNumberOfFlags);
+ return static_cast<GVNFlag>(i);
+}
+
+
class DecompositionResult V8_FINAL BASE_EMBEDDED {
public:
DecompositionResult() : base_(NULL), offset_(0), scale_(0) {}
@@ -542,7 +543,62 @@ class DecompositionResult V8_FINAL BASE_EMBEDDED {
};
-typedef EnumSet<GVNFlag> GVNFlagSet;
+typedef EnumSet<GVNFlag, int32_t> GVNFlagSet;
+
+
+// This class encapsulates encoding and decoding of sources positions from
+// which hydrogen values originated.
+// When FLAG_track_hydrogen_positions is set this object encodes the
+// identifier of the inlining and absolute offset from the start of the
+// inlined function.
+// When the flag is not set we simply track absolute offset from the
+// script start.
+class HSourcePosition {
+ public:
+ HSourcePosition(const HSourcePosition& other) : value_(other.value_) { }
+
+ static HSourcePosition Unknown() {
+ return HSourcePosition(RelocInfo::kNoPosition);
+ }
+
+ bool IsUnknown() const { return value_ == RelocInfo::kNoPosition; }
+
+ int position() const { return PositionField::decode(value_); }
+ void set_position(int position) {
+ if (FLAG_hydrogen_track_positions) {
+ value_ = static_cast<int>(PositionField::update(value_, position));
+ } else {
+ value_ = position;
+ }
+ }
+
+ int inlining_id() const { return InliningIdField::decode(value_); }
+ void set_inlining_id(int inlining_id) {
+ if (FLAG_hydrogen_track_positions) {
+ value_ = static_cast<int>(InliningIdField::update(value_, inlining_id));
+ }
+ }
+
+ int raw() const { return value_; }
+
+ void PrintTo(FILE* f);
+
+ private:
+ typedef BitField<int, 0, 9> InliningIdField;
+
+ // Offset from the start of the inlined function.
+ typedef BitField<int, 9, 22> PositionField;
+
+ // On HPositionInfo can use this constructor.
+ explicit HSourcePosition(int value) : value_(value) { }
+
+ friend class HPositionInfo;
+
+ // If FLAG_hydrogen_track_positions is set contains bitfields InliningIdField
+ // and PositionField.
+ // Otherwise contains absolute offset from the script start.
+ int value_;
+};
class HValue : public ZoneObject {
@@ -574,7 +630,7 @@ class HValue : public ZoneObject {
kIsDead,
// Instructions that are allowed to produce full range unsigned integer
// values are marked with kUint32 flag. If arithmetic shift or a load from
- // EXTERNAL_UNSIGNED_INT_ELEMENTS array is not marked with this flag
+ // EXTERNAL_UINT32_ELEMENTS array is not marked with this flag
// it will deoptimize if result does not fit into signed integer range.
// HGraph::ComputeSafeUint32Operations is responsible for setting this
// flag.
@@ -593,18 +649,6 @@ class HValue : public ZoneObject {
STATIC_ASSERT(kLastFlag < kBitsPerInt);
- static const int kChangesToDependsFlagsLeftShift = 1;
-
- static GVNFlag ChangesFlagFromInt(int x) {
- return static_cast<GVNFlag>(x * 2);
- }
- static GVNFlag DependsOnFlagFromInt(int x) {
- return static_cast<GVNFlag>(x * 2 + 1);
- }
- static GVNFlagSet ConvertChangesToDependsFlags(GVNFlagSet flags) {
- return GVNFlagSet(flags.ToIntegral() << kChangesToDependsFlagsLeftShift);
- }
-
static HValue* cast(HValue* value) { return value; }
enum Opcode {
@@ -638,11 +682,15 @@ class HValue : public ZoneObject {
flags_(0) {}
virtual ~HValue() {}
- virtual int position() const { return RelocInfo::kNoPosition; }
+ virtual HSourcePosition position() const {
+ return HSourcePosition::Unknown();
+ }
+ virtual HSourcePosition operand_position(int index) const {
+ return position();
+ }
HBasicBlock* block() const { return block_; }
void SetBlock(HBasicBlock* block);
- int LoopWeight() const;
// Note: Never call this method for an unlinked value.
Isolate* isolate() const;
@@ -780,43 +828,38 @@ class HValue : public ZoneObject {
// of uses is non-empty.
bool HasAtLeastOneUseWithFlagAndNoneWithout(Flag f) const;
- GVNFlagSet gvn_flags() const { return gvn_flags_; }
- void SetGVNFlag(GVNFlag f) { gvn_flags_.Add(f); }
- void ClearGVNFlag(GVNFlag f) { gvn_flags_.Remove(f); }
- bool CheckGVNFlag(GVNFlag f) const { return gvn_flags_.Contains(f); }
- void SetAllSideEffects() { gvn_flags_.Add(AllSideEffectsFlagSet()); }
+ GVNFlagSet ChangesFlags() const { return changes_flags_; }
+ GVNFlagSet DependsOnFlags() const { return depends_on_flags_; }
+ void SetChangesFlag(GVNFlag f) { changes_flags_.Add(f); }
+ void SetDependsOnFlag(GVNFlag f) { depends_on_flags_.Add(f); }
+ void ClearChangesFlag(GVNFlag f) { changes_flags_.Remove(f); }
+ void ClearDependsOnFlag(GVNFlag f) { depends_on_flags_.Remove(f); }
+ bool CheckChangesFlag(GVNFlag f) const {
+ return changes_flags_.Contains(f);
+ }
+ bool CheckDependsOnFlag(GVNFlag f) const {
+ return depends_on_flags_.Contains(f);
+ }
+ void SetAllSideEffects() { changes_flags_.Add(AllSideEffectsFlagSet()); }
void ClearAllSideEffects() {
- gvn_flags_.Remove(AllSideEffectsFlagSet());
+ changes_flags_.Remove(AllSideEffectsFlagSet());
}
bool HasSideEffects() const {
- return gvn_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
+ return changes_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
}
bool HasObservableSideEffects() const {
return !CheckFlag(kHasNoObservableSideEffects) &&
- gvn_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
- }
-
- GVNFlagSet DependsOnFlags() const {
- GVNFlagSet result = gvn_flags_;
- result.Intersect(AllDependsOnFlagSet());
- return result;
+ changes_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
}
GVNFlagSet SideEffectFlags() const {
- GVNFlagSet result = gvn_flags_;
+ GVNFlagSet result = ChangesFlags();
result.Intersect(AllSideEffectsFlagSet());
return result;
}
- GVNFlagSet ChangesFlags() const {
- GVNFlagSet result = gvn_flags_;
- result.Intersect(AllChangesFlagSet());
- return result;
- }
-
GVNFlagSet ObservableChangesFlags() const {
- GVNFlagSet result = gvn_flags_;
- result.Intersect(AllChangesFlagSet());
+ GVNFlagSet result = ChangesFlags();
result.Intersect(AllObservableSideEffectsFlagSet());
return result;
}
@@ -882,9 +925,11 @@ class HValue : public ZoneObject {
// This function must be overridden for instructions which have the
// kTrackSideEffectDominators flag set, to track instructions that are
// dominating side effects.
- virtual void HandleSideEffectDominator(GVNFlag side_effect,
+ // It returns true if it removed an instruction which had side effects.
+ virtual bool HandleSideEffectDominator(GVNFlag side_effect,
HValue* dominator) {
UNREACHABLE();
+ return false;
}
// Check if this instruction has some reason that prevents elimination.
@@ -955,20 +1000,9 @@ class HValue : public ZoneObject {
representation_ = r;
}
- static GVNFlagSet AllDependsOnFlagSet() {
+ static GVNFlagSet AllFlagSet() {
GVNFlagSet result;
- // Create changes mask.
-#define ADD_FLAG(type) result.Add(kDependsOn##type);
- GVN_TRACKED_FLAG_LIST(ADD_FLAG)
- GVN_UNTRACKED_FLAG_LIST(ADD_FLAG)
-#undef ADD_FLAG
- return result;
- }
-
- static GVNFlagSet AllChangesFlagSet() {
- GVNFlagSet result;
- // Create changes mask.
-#define ADD_FLAG(type) result.Add(kChanges##type);
+#define ADD_FLAG(Type) result.Add(k##Type);
GVN_TRACKED_FLAG_LIST(ADD_FLAG)
GVN_UNTRACKED_FLAG_LIST(ADD_FLAG)
#undef ADD_FLAG
@@ -977,19 +1011,19 @@ class HValue : public ZoneObject {
// A flag mask to mark an instruction as having arbitrary side effects.
static GVNFlagSet AllSideEffectsFlagSet() {
- GVNFlagSet result = AllChangesFlagSet();
- result.Remove(kChangesOsrEntries);
+ GVNFlagSet result = AllFlagSet();
+ result.Remove(kOsrEntries);
return result;
}
// A flag mask of all side effects that can make observable changes in
// an executing program (i.e. are not safe to repeat, move or remove);
static GVNFlagSet AllObservableSideEffectsFlagSet() {
- GVNFlagSet result = AllChangesFlagSet();
- result.Remove(kChangesNewSpacePromotion);
- result.Remove(kChangesElementsKind);
- result.Remove(kChangesElementsPointer);
- result.Remove(kChangesMaps);
+ GVNFlagSet result = AllFlagSet();
+ result.Remove(kNewSpacePromotion);
+ result.Remove(kElementsKind);
+ result.Remove(kElementsPointer);
+ result.Remove(kMaps);
return result;
}
@@ -1010,7 +1044,8 @@ class HValue : public ZoneObject {
HUseListNode* use_list_;
Range* range_;
int flags_;
- GVNFlagSet gvn_flags_;
+ GVNFlagSet changes_flags_;
+ GVNFlagSet depends_on_flags_;
private:
virtual bool IsDeletable() const { return false; }
@@ -1102,6 +1137,99 @@ class HValue : public ZoneObject {
}
+// A helper class to represent per-operand position information attached to
+// the HInstruction in the compact form. Uses tagging to distinguish between
+// case when only instruction's position is available and case when operands'
+// positions are also available.
+// In the first case it contains intruction's position as a tagged value.
+// In the second case it points to an array which contains instruction's
+// position and operands' positions.
+class HPositionInfo {
+ public:
+ explicit HPositionInfo(int pos) : data_(TagPosition(pos)) { }
+
+ HSourcePosition position() const {
+ if (has_operand_positions()) {
+ return operand_positions()[kInstructionPosIndex];
+ }
+ return HSourcePosition(static_cast<int>(UntagPosition(data_)));
+ }
+
+ void set_position(HSourcePosition pos) {
+ if (has_operand_positions()) {
+ operand_positions()[kInstructionPosIndex] = pos;
+ } else {
+ data_ = TagPosition(pos.raw());
+ }
+ }
+
+ void ensure_storage_for_operand_positions(Zone* zone, int operand_count) {
+ if (has_operand_positions()) {
+ return;
+ }
+
+ const int length = kFirstOperandPosIndex + operand_count;
+ HSourcePosition* positions =
+ zone->NewArray<HSourcePosition>(length);
+ for (int i = 0; i < length; i++) {
+ positions[i] = HSourcePosition::Unknown();
+ }
+
+ const HSourcePosition pos = position();
+ data_ = reinterpret_cast<intptr_t>(positions);
+ set_position(pos);
+
+ ASSERT(has_operand_positions());
+ }
+
+ HSourcePosition operand_position(int idx) const {
+ if (!has_operand_positions()) {
+ return position();
+ }
+ return *operand_position_slot(idx);
+ }
+
+ void set_operand_position(int idx, HSourcePosition pos) {
+ *operand_position_slot(idx) = pos;
+ }
+
+ private:
+ static const intptr_t kInstructionPosIndex = 0;
+ static const intptr_t kFirstOperandPosIndex = 1;
+
+ HSourcePosition* operand_position_slot(int idx) const {
+ ASSERT(has_operand_positions());
+ return &(operand_positions()[kFirstOperandPosIndex + idx]);
+ }
+
+ bool has_operand_positions() const {
+ return !IsTaggedPosition(data_);
+ }
+
+ HSourcePosition* operand_positions() const {
+ ASSERT(has_operand_positions());
+ return reinterpret_cast<HSourcePosition*>(data_);
+ }
+
+ static const intptr_t kPositionTag = 1;
+ static const intptr_t kPositionShift = 1;
+ static bool IsTaggedPosition(intptr_t val) {
+ return (val & kPositionTag) != 0;
+ }
+ static intptr_t UntagPosition(intptr_t val) {
+ ASSERT(IsTaggedPosition(val));
+ return val >> kPositionShift;
+ }
+ static intptr_t TagPosition(intptr_t val) {
+ const intptr_t result = (val << kPositionShift) | kPositionTag;
+ ASSERT(UntagPosition(result) == val);
+ return result;
+ }
+
+ intptr_t data_;
+};
+
+
class HInstruction : public HValue {
public:
HInstruction* next() const { return next_; }
@@ -1112,16 +1240,42 @@ class HInstruction : public HValue {
bool IsLinked() const { return block() != NULL; }
void Unlink();
+
void InsertBefore(HInstruction* next);
+
+ template<class T> T* Prepend(T* instr) {
+ instr->InsertBefore(this);
+ return instr;
+ }
+
void InsertAfter(HInstruction* previous);
+ template<class T> T* Append(T* instr) {
+ instr->InsertAfter(this);
+ return instr;
+ }
+
// The position is a write-once variable.
- virtual int position() const V8_OVERRIDE { return position_; }
- bool has_position() const { return position_ != RelocInfo::kNoPosition; }
- void set_position(int position) {
+ virtual HSourcePosition position() const V8_OVERRIDE {
+ return HSourcePosition(position_.position());
+ }
+ bool has_position() const {
+ return !position().IsUnknown();
+ }
+ void set_position(HSourcePosition position) {
ASSERT(!has_position());
- ASSERT(position != RelocInfo::kNoPosition);
- position_ = position;
+ ASSERT(!position.IsUnknown());
+ position_.set_position(position);
+ }
+
+ virtual HSourcePosition operand_position(int index) const V8_OVERRIDE {
+ const HSourcePosition pos = position_.operand_position(index);
+ return pos.IsUnknown() ? position() : pos;
+ }
+ void set_operand_position(Zone* zone, int index, HSourcePosition pos) {
+ ASSERT(0 <= index && index < OperandCount());
+ position_.ensure_storage_for_operand_positions(zone, OperandCount());
+ position_.set_operand_position(index, pos);
}
bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); }
@@ -1132,7 +1286,7 @@ class HInstruction : public HValue {
virtual void Verify() V8_OVERRIDE;
#endif
- virtual bool IsCall() { return false; }
+ virtual bool HasStackCheck() { return false; }
DECLARE_ABSTRACT_INSTRUCTION(Instruction)
@@ -1142,7 +1296,7 @@ class HInstruction : public HValue {
next_(NULL),
previous_(NULL),
position_(RelocInfo::kNoPosition) {
- SetGVNFlag(kDependsOnOsrEntries);
+ SetDependsOnFlag(kOsrEntries);
}
virtual void DeleteFromGraph() V8_OVERRIDE { Unlink(); }
@@ -1157,7 +1311,7 @@ class HInstruction : public HValue {
HInstruction* next_;
HInstruction* previous_;
- int position_;
+ HPositionInfo position_;
friend class HBasicBlock;
};
@@ -1321,11 +1475,11 @@ class HGoto V8_FINAL : public HTemplateControlInstruction<1, 0> {
class HDeoptimize V8_FINAL : public HTemplateControlInstruction<1, 0> {
public:
- static HInstruction* New(Zone* zone,
- HValue* context,
- const char* reason,
- Deoptimizer::BailoutType type,
- HBasicBlock* unreachable_continuation) {
+ static HDeoptimize* New(Zone* zone,
+ HValue* context,
+ const char* reason,
+ Deoptimizer::BailoutType type,
+ HBasicBlock* unreachable_continuation) {
return new(zone) HDeoptimize(reason, type, unreachable_continuation);
}
@@ -1410,18 +1564,39 @@ class HBranch V8_FINAL : public HUnaryControlInstruction {
class HCompareMap V8_FINAL : public HUnaryControlInstruction {
public:
- DECLARE_INSTRUCTION_FACTORY_P2(HCompareMap, HValue*, Handle<Map>);
- DECLARE_INSTRUCTION_FACTORY_P4(HCompareMap, HValue*, Handle<Map>,
+ DECLARE_INSTRUCTION_FACTORY_P3(HCompareMap, HValue*, Handle<Map>,
+ CompilationInfo*);
+ DECLARE_INSTRUCTION_FACTORY_P5(HCompareMap, HValue*, Handle<Map>,
+ CompilationInfo*,
HBasicBlock*, HBasicBlock*);
+ virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE {
+ if (known_successor_index() != kNoKnownSuccessorIndex) {
+ *block = SuccessorAt(known_successor_index());
+ return true;
+ }
+ *block = NULL;
+ return false;
+ }
+
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
+ static const int kNoKnownSuccessorIndex = -1;
+ int known_successor_index() const { return known_successor_index_; }
+ void set_known_successor_index(int known_successor_index) {
+ known_successor_index_ = known_successor_index;
+ }
+
Unique<Map> map() const { return map_; }
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
return Representation::Tagged();
}
+ bool is_stable() const {
+ return is_stable_;
+ }
+
DECLARE_CONCRETE_INSTRUCTION(CompareMap)
protected:
@@ -1430,13 +1605,22 @@ class HCompareMap V8_FINAL : public HUnaryControlInstruction {
private:
HCompareMap(HValue* value,
Handle<Map> map,
+ CompilationInfo* info,
HBasicBlock* true_target = NULL,
HBasicBlock* false_target = NULL)
: HUnaryControlInstruction(value, true_target, false_target),
- map_(Unique<Map>(map)) {
+ known_successor_index_(kNoKnownSuccessorIndex), map_(Unique<Map>(map)) {
ASSERT(!map.is_null());
+ is_stable_ = map->is_stable();
+
+ if (is_stable_) {
+ map->AddDependentCompilationInfo(
+ DependentCode::kPrototypeCheckGroup, info);
+ }
}
+ int known_successor_index_;
+ bool is_stable_;
Unique<Map> map_;
};
@@ -1524,28 +1708,6 @@ class HUnaryOperation : public HTemplateInstruction<1> {
};
-class HThrow V8_FINAL : public HTemplateInstruction<2> {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HThrow, HValue*);
-
- virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- return Representation::Tagged();
- }
-
- HValue* context() { return OperandAt(0); }
- HValue* value() { return OperandAt(1); }
-
- DECLARE_CONCRETE_INSTRUCTION(Throw)
-
- private:
- HThrow(HValue* context, HValue* value) {
- SetOperandAt(0, context);
- SetOperandAt(1, value);
- SetAllSideEffects();
- }
-};
-
-
class HUseConst V8_FINAL : public HUnaryOperation {
public:
DECLARE_INSTRUCTION_FACTORY_P1(HUseConst, HValue*);
@@ -1563,7 +1725,8 @@ class HUseConst V8_FINAL : public HUnaryOperation {
class HForceRepresentation V8_FINAL : public HTemplateInstruction<1> {
public:
- DECLARE_INSTRUCTION_FACTORY_P2(HForceRepresentation, HValue*, Representation);
+ static HInstruction* New(Zone* zone, HValue* context, HValue* value,
+ Representation required_representation);
HValue* value() { return OperandAt(0); }
@@ -1607,7 +1770,7 @@ class HChange V8_FINAL : public HUnaryOperation {
set_type(HType::Smi());
} else {
set_type(HType::TaggedNumber());
- if (to.IsTagged()) SetGVNFlag(kChangesNewSpacePromotion);
+ if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
}
}
@@ -1853,7 +2016,7 @@ class HStackCheck V8_FINAL : public HTemplateInstruction<1> {
private:
HStackCheck(HValue* context, Type type) : type_(type) {
SetOperandAt(0, context);
- SetGVNFlag(kChangesNewSpacePromotion);
+ SetChangesFlag(kNewSpacePromotion);
}
Type type_;
@@ -1861,8 +2024,7 @@ class HStackCheck V8_FINAL : public HTemplateInstruction<1> {
enum InliningKind {
- NORMAL_RETURN, // Normal function/method call and return.
- DROP_EXTRA_ON_RETURN, // Drop an extra value from the environment on return.
+ NORMAL_RETURN, // Drop the function from the environment on return.
CONSTRUCT_CALL_RETURN, // Either use allocated receiver or return value.
GETTER_CALL_RETURN, // Returning from a getter, need to restore context.
SETTER_CALL_RETURN // Use the RHS of the assignment as the return value.
@@ -1881,11 +2043,10 @@ class HEnterInlined V8_FINAL : public HTemplateInstruction<0> {
FunctionLiteral* function,
InliningKind inlining_kind,
Variable* arguments_var,
- HArgumentsObject* arguments_object,
- bool undefined_receiver) {
+ HArgumentsObject* arguments_object) {
return new(zone) HEnterInlined(closure, arguments_count, function,
inlining_kind, arguments_var,
- arguments_object, undefined_receiver, zone);
+ arguments_object, zone);
}
void RegisterReturnTarget(HBasicBlock* return_target, Zone* zone);
@@ -1899,7 +2060,6 @@ class HEnterInlined V8_FINAL : public HTemplateInstruction<0> {
void set_arguments_pushed() { arguments_pushed_ = true; }
FunctionLiteral* function() const { return function_; }
InliningKind inlining_kind() const { return inlining_kind_; }
- bool undefined_receiver() const { return undefined_receiver_; }
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
return Representation::None();
@@ -1917,7 +2077,6 @@ class HEnterInlined V8_FINAL : public HTemplateInstruction<0> {
InliningKind inlining_kind,
Variable* arguments_var,
HArgumentsObject* arguments_object,
- bool undefined_receiver,
Zone* zone)
: closure_(closure),
arguments_count_(arguments_count),
@@ -1926,7 +2085,6 @@ class HEnterInlined V8_FINAL : public HTemplateInstruction<0> {
inlining_kind_(inlining_kind),
arguments_var_(arguments_var),
arguments_object_(arguments_object),
- undefined_receiver_(undefined_receiver),
return_targets_(2, zone) {
}
@@ -1937,7 +2095,6 @@ class HEnterInlined V8_FINAL : public HTemplateInstruction<0> {
InliningKind inlining_kind_;
Variable* arguments_var_;
HArgumentsObject* arguments_object_;
- bool undefined_receiver_;
ZoneList<HBasicBlock*> return_targets_;
};
@@ -2008,29 +2165,6 @@ class HThisFunction V8_FINAL : public HTemplateInstruction<0> {
};
-class HOuterContext V8_FINAL : public HUnaryOperation {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HOuterContext, HValue*);
-
- DECLARE_CONCRETE_INSTRUCTION(OuterContext);
-
- virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- return Representation::Tagged();
- }
-
- protected:
- virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
-
- private:
- explicit HOuterContext(HValue* inner) : HUnaryOperation(inner) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- }
-
- virtual bool IsDeletable() const V8_OVERRIDE { return true; }
-};
-
-
class HDeclareGlobals V8_FINAL : public HUnaryOperation {
public:
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HDeclareGlobals,
@@ -2063,53 +2197,6 @@ class HDeclareGlobals V8_FINAL : public HUnaryOperation {
};
-class HGlobalObject V8_FINAL : public HUnaryOperation {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P0(HGlobalObject);
-
- DECLARE_CONCRETE_INSTRUCTION(GlobalObject)
-
- virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- return Representation::Tagged();
- }
-
- protected:
- virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
-
- private:
- explicit HGlobalObject(HValue* context) : HUnaryOperation(context) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- }
-
- virtual bool IsDeletable() const V8_OVERRIDE { return true; }
-};
-
-
-class HGlobalReceiver V8_FINAL : public HUnaryOperation {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HGlobalReceiver, HValue*);
-
- DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver)
-
- virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- return Representation::Tagged();
- }
-
- protected:
- virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
-
- private:
- explicit HGlobalReceiver(HValue* global_object)
- : HUnaryOperation(global_object) {
- set_representation(Representation::Tagged());
- SetFlag(kUseGVN);
- }
-
- virtual bool IsDeletable() const V8_OVERRIDE { return true; }
-};
-
-
template <int V>
class HCall : public HTemplateInstruction<V> {
public:
@@ -2131,8 +2218,6 @@ class HCall : public HTemplateInstruction<V> {
return -argument_count();
}
- virtual bool IsCall() V8_FINAL V8_OVERRIDE { return true; }
-
private:
int argument_count_;
};
@@ -2176,174 +2261,208 @@ class HBinaryCall : public HCall<2> {
};
-class HInvokeFunction V8_FINAL : public HBinaryCall {
+class HCallJSFunction V8_FINAL : public HCall<1> {
public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInvokeFunction, HValue*, int);
-
- HInvokeFunction(HValue* context,
- HValue* function,
- Handle<JSFunction> known_function,
- int argument_count)
- : HBinaryCall(context, function, argument_count),
- known_function_(known_function) {
- formal_parameter_count_ = known_function.is_null()
- ? 0 : known_function->shared()->formal_parameter_count();
- }
-
- static HInvokeFunction* New(Zone* zone,
+ static HCallJSFunction* New(Zone* zone,
HValue* context,
HValue* function,
- Handle<JSFunction> known_function,
- int argument_count) {
- return new(zone) HInvokeFunction(context, function,
- known_function, argument_count);
+ int argument_count,
+ bool pass_argument_count);
+
+ HValue* function() { return OperandAt(0); }
+
+ virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
+
+ virtual Representation RequiredInputRepresentation(
+ int index) V8_FINAL V8_OVERRIDE {
+ ASSERT(index == 0);
+ return Representation::Tagged();
}
- HValue* context() { return first(); }
- HValue* function() { return second(); }
- Handle<JSFunction> known_function() { return known_function_; }
- int formal_parameter_count() const { return formal_parameter_count_; }
+ bool pass_argument_count() const { return pass_argument_count_; }
- DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
+ virtual bool HasStackCheck() V8_FINAL V8_OVERRIDE {
+ return has_stack_check_;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(CallJSFunction)
private:
- HInvokeFunction(HValue* context, HValue* function, int argument_count)
- : HBinaryCall(context, function, argument_count) {
+ // The argument count includes the receiver.
+ HCallJSFunction(HValue* function,
+ int argument_count,
+ bool pass_argument_count,
+ bool has_stack_check)
+ : HCall<1>(argument_count),
+ pass_argument_count_(pass_argument_count),
+ has_stack_check_(has_stack_check) {
+ SetOperandAt(0, function);
}
- Handle<JSFunction> known_function_;
- int formal_parameter_count_;
+ bool pass_argument_count_;
+ bool has_stack_check_;
};
-class HCallConstantFunction V8_FINAL : public HCall<0> {
+class HCallWithDescriptor V8_FINAL : public HInstruction {
public:
- DECLARE_INSTRUCTION_FACTORY_P2(HCallConstantFunction,
- Handle<JSFunction>,
- int);
-
- Handle<JSFunction> function() const { return function_; }
- int formal_parameter_count() const { return formal_parameter_count_; }
-
- bool IsApplyFunction() const {
- return function_->code() ==
- function_->GetIsolate()->builtins()->builtin(Builtins::kFunctionApply);
+ static HCallWithDescriptor* New(Zone* zone, HValue* context,
+ HValue* target,
+ int argument_count,
+ const CallInterfaceDescriptor* descriptor,
+ Vector<HValue*>& operands) {
+ ASSERT(operands.length() == descriptor->environment_length());
+ HCallWithDescriptor* res =
+ new(zone) HCallWithDescriptor(target, argument_count,
+ descriptor, operands, zone);
+ return res;
}
- virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
-
- virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- return Representation::None();
+ virtual int OperandCount() V8_FINAL V8_OVERRIDE { return values_.length(); }
+ virtual HValue* OperandAt(int index) const V8_FINAL V8_OVERRIDE {
+ return values_[index];
}
- DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction)
-
- private:
- HCallConstantFunction(Handle<JSFunction> function, int argument_count)
- : HCall<0>(argument_count),
- function_(function),
- formal_parameter_count_(function->shared()->formal_parameter_count()) {}
-
- Handle<JSFunction> function_;
- int formal_parameter_count_;
-};
-
+ virtual Representation RequiredInputRepresentation(
+ int index) V8_FINAL V8_OVERRIDE {
+ if (index == 0) {
+ return Representation::Tagged();
+ } else {
+ int par_index = index - 1;
+ ASSERT(par_index < descriptor_->environment_length());
+ return descriptor_->GetParameterRepresentation(par_index);
+ }
+ }
-class HCallKeyed V8_FINAL : public HBinaryCall {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallKeyed, HValue*, int);
+ DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor)
- HValue* context() { return first(); }
- HValue* key() { return second(); }
+ virtual HType CalculateInferredType() V8_FINAL V8_OVERRIDE {
+ return HType::Tagged();
+ }
- DECLARE_CONCRETE_INSTRUCTION(CallKeyed)
+ virtual int argument_count() const {
+ return argument_count_;
+ }
- private:
- HCallKeyed(HValue* context, HValue* key, int argument_count)
- : HBinaryCall(context, key, argument_count) {
+ virtual int argument_delta() const V8_OVERRIDE {
+ return -argument_count_;
}
-};
+ const CallInterfaceDescriptor* descriptor() const {
+ return descriptor_;
+ }
-class HCallNamed V8_FINAL : public HUnaryCall {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallNamed, Handle<String>, int);
+ HValue* target() {
+ return OperandAt(0);
+ }
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
- HValue* context() { return value(); }
- Handle<String> name() const { return name_; }
+ private:
+ // The argument count includes the receiver.
+ HCallWithDescriptor(HValue* target,
+ int argument_count,
+ const CallInterfaceDescriptor* descriptor,
+ Vector<HValue*>& operands,
+ Zone* zone)
+ : descriptor_(descriptor),
+ values_(descriptor->environment_length() + 1, zone) {
+ argument_count_ = argument_count;
+ AddOperand(target, zone);
+ for (int i = 0; i < operands.length(); i++) {
+ AddOperand(operands[i], zone);
+ }
+ this->set_representation(Representation::Tagged());
+ this->SetAllSideEffects();
+ }
- DECLARE_CONCRETE_INSTRUCTION(CallNamed)
+ void AddOperand(HValue* v, Zone* zone) {
+ values_.Add(NULL, zone);
+ SetOperandAt(values_.length() - 1, v);
+ }
- private:
- HCallNamed(HValue* context, Handle<String> name, int argument_count)
- : HUnaryCall(context, argument_count), name_(name) {
+ void InternalSetOperandAt(int index,
+ HValue* value) V8_FINAL V8_OVERRIDE {
+ values_[index] = value;
}
- Handle<String> name_;
+ const CallInterfaceDescriptor* descriptor_;
+ ZoneList<HValue*> values_;
+ int argument_count_;
};
-class HCallFunction V8_FINAL : public HBinaryCall {
+class HInvokeFunction V8_FINAL : public HBinaryCall {
public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallFunction, HValue*, int);
-
- HValue* context() { return first(); }
- HValue* function() { return second(); }
-
- DECLARE_CONCRETE_INSTRUCTION(CallFunction)
+ DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInvokeFunction, HValue*, int);
- private:
- HCallFunction(HValue* context, HValue* function, int argument_count)
- : HBinaryCall(context, function, argument_count) {
+ HInvokeFunction(HValue* context,
+ HValue* function,
+ Handle<JSFunction> known_function,
+ int argument_count)
+ : HBinaryCall(context, function, argument_count),
+ known_function_(known_function) {
+ formal_parameter_count_ = known_function.is_null()
+ ? 0 : known_function->shared()->formal_parameter_count();
+ has_stack_check_ = !known_function.is_null() &&
+ (known_function->code()->kind() == Code::FUNCTION ||
+ known_function->code()->kind() == Code::OPTIMIZED_FUNCTION);
}
-};
-
-class HCallGlobal V8_FINAL : public HUnaryCall {
- public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallGlobal, Handle<String>, int);
+ 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 void PrintDataTo(StringStream* stream) V8_OVERRIDE;
+ HValue* context() { return first(); }
+ HValue* function() { return second(); }
+ Handle<JSFunction> known_function() { return known_function_; }
+ int formal_parameter_count() const { return formal_parameter_count_; }
- HValue* context() { return value(); }
- Handle<String> name() const { return name_; }
+ virtual bool HasStackCheck() V8_FINAL V8_OVERRIDE {
+ return has_stack_check_;
+ }
- DECLARE_CONCRETE_INSTRUCTION(CallGlobal)
+ DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
private:
- HCallGlobal(HValue* context, Handle<String> name, int argument_count)
- : HUnaryCall(context, argument_count), name_(name) {
+ HInvokeFunction(HValue* context, HValue* function, int argument_count)
+ : HBinaryCall(context, function, argument_count),
+ has_stack_check_(false) {
}
- Handle<String> name_;
+ Handle<JSFunction> known_function_;
+ int formal_parameter_count_;
+ bool has_stack_check_;
};
-class HCallKnownGlobal V8_FINAL : public HCall<0> {
+class HCallFunction V8_FINAL : public HBinaryCall {
public:
- DECLARE_INSTRUCTION_FACTORY_P2(HCallKnownGlobal, Handle<JSFunction>, int);
-
- virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
+ DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallFunction, HValue*, int);
+ DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(
+ HCallFunction, HValue*, int, CallFunctionFlags);
- Handle<JSFunction> target() const { return target_; }
- int formal_parameter_count() const { return formal_parameter_count_; }
+ HValue* context() { return first(); }
+ HValue* function() { return second(); }
+ CallFunctionFlags function_flags() const { return function_flags_; }
- virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- return Representation::None();
- }
+ DECLARE_CONCRETE_INSTRUCTION(CallFunction)
- DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal)
+ virtual int argument_delta() const V8_OVERRIDE { return -argument_count(); }
private:
- HCallKnownGlobal(Handle<JSFunction> target, int argument_count)
- : HCall<0>(argument_count),
- target_(target),
- formal_parameter_count_(target->shared()->formal_parameter_count()) { }
-
- Handle<JSFunction> target_;
- int formal_parameter_count_;
+ HCallFunction(HValue* context,
+ HValue* function,
+ int argument_count,
+ CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS)
+ : HBinaryCall(context, function, argument_count), function_flags_(flags) {
+ }
+ CallFunctionFlags function_flags_;
};
@@ -2364,10 +2483,9 @@ class HCallNew V8_FINAL : public HBinaryCall {
class HCallNewArray V8_FINAL : public HBinaryCall {
public:
- DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HCallNewArray,
+ DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HCallNewArray,
HValue*,
int,
- Handle<Cell>,
ElementsKind);
HValue* context() { return first(); }
@@ -2375,23 +2493,17 @@ class HCallNewArray V8_FINAL : public HBinaryCall {
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
- Handle<Cell> property_cell() const {
- return type_cell_;
- }
-
ElementsKind elements_kind() const { return elements_kind_; }
DECLARE_CONCRETE_INSTRUCTION(CallNewArray)
private:
HCallNewArray(HValue* context, HValue* constructor, int argument_count,
- Handle<Cell> type_cell, ElementsKind elements_kind)
+ ElementsKind elements_kind)
: HBinaryCall(context, constructor, argument_count),
- elements_kind_(elements_kind),
- type_cell_(type_cell) {}
+ elements_kind_(elements_kind) {}
ElementsKind elements_kind_;
- Handle<Cell> type_cell_;
};
@@ -2452,35 +2564,13 @@ class HMapEnumLength V8_FINAL : public HUnaryOperation {
: HUnaryOperation(value, HType::Smi()) {
set_representation(Representation::Smi());
SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnMaps);
+ SetDependsOnFlag(kMaps);
}
virtual bool IsDeletable() const V8_OVERRIDE { return true; }
};
-class HElementsKind V8_FINAL : public HUnaryOperation {
- public:
- explicit HElementsKind(HValue* value) : HUnaryOperation(value) {
- set_representation(Representation::Integer32());
- SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnElementsKind);
- }
-
- virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(ElementsKind)
-
- protected:
- virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
-
- private:
- virtual bool IsDeletable() const V8_OVERRIDE { return true; }
-};
-
-
class HUnaryMathOperation V8_FINAL : public HTemplateInstruction<2> {
public:
static HInstruction* New(Zone* zone,
@@ -2507,9 +2597,6 @@ class HUnaryMathOperation V8_FINAL : public HTemplateInstruction<2> {
case kMathPowHalf:
case kMathLog:
case kMathExp:
- case kMathSin:
- case kMathCos:
- case kMathTan:
return Representation::Double();
case kMathAbs:
return representation();
@@ -2551,16 +2638,9 @@ class HUnaryMathOperation V8_FINAL : public HTemplateInstruction<2> {
SetFlag(kFlexibleRepresentation);
// TODO(svenpanne) This flag is actually only needed if representation()
// is tagged, and not when it is an unboxed double or unboxed integer.
- SetGVNFlag(kChangesNewSpacePromotion);
+ SetChangesFlag(kNewSpacePromotion);
break;
case kMathLog:
- case kMathSin:
- case kMathCos:
- case kMathTan:
- set_representation(Representation::Double());
- // These operations use the TranscendentalCache, so they may allocate.
- SetGVNFlag(kChangesNewSpacePromotion);
- break;
case kMathExp:
case kMathSqrt:
case kMathPowHalf:
@@ -2575,6 +2655,9 @@ class HUnaryMathOperation V8_FINAL : public HTemplateInstruction<2> {
virtual bool IsDeletable() const V8_OVERRIDE { return true; }
+ HValue* SimplifiedDividendForMathFloorOfDiv(HDiv* hdiv);
+ HValue* SimplifiedDivisorForMathFloorOfDiv(HDiv* hdiv);
+
BuiltinFunctionId op_;
};
@@ -2604,7 +2687,7 @@ class HLoadRoot V8_FINAL : public HTemplateInstruction<0> {
SetFlag(kUseGVN);
// TODO(bmeurer): We'll need kDependsOnRoots once we add the
// corresponding HStoreRoot instruction.
- SetGVNFlag(kDependsOnCalls);
+ SetDependsOnFlag(kCalls);
}
virtual bool IsDeletable() const V8_OVERRIDE { return true; }
@@ -2613,49 +2696,18 @@ class HLoadRoot V8_FINAL : public HTemplateInstruction<0> {
};
-class HLoadExternalArrayPointer V8_FINAL : public HUnaryOperation {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HLoadExternalArrayPointer, HValue*);
-
- virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- return Representation::Tagged();
- }
-
- virtual HType CalculateInferredType() V8_OVERRIDE {
- return HType::None();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer)
-
- protected:
- virtual bool DataEquals(HValue* other) V8_OVERRIDE { 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 V8_OVERRIDE { return true; }
-};
-
-
class HCheckMaps V8_FINAL : public HTemplateInstruction<2> {
public:
static HCheckMaps* New(Zone* zone, HValue* context, HValue* value,
Handle<Map> map, CompilationInfo* info,
- HValue *typecheck = NULL);
+ HValue* typecheck = NULL);
static HCheckMaps* New(Zone* zone, HValue* context,
HValue* value, SmallMapList* maps,
- HValue *typecheck = NULL) {
+ CompilationInfo* info,
+ HValue* typecheck = NULL) {
HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck);
for (int i = 0; i < maps->length(); i++) {
- check_map->Add(maps->at(i), zone);
+ check_map->Add(maps->at(i), info, zone);
}
return check_map;
}
@@ -2666,19 +2718,31 @@ class HCheckMaps V8_FINAL : public HTemplateInstruction<2> {
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
return Representation::Tagged();
}
- virtual void HandleSideEffectDominator(GVNFlag side_effect,
+ virtual bool HandleSideEffectDominator(GVNFlag side_effect,
HValue* dominator) V8_OVERRIDE;
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
HValue* value() { return OperandAt(0); }
+ HValue* typecheck() { return OperandAt(1); }
Unique<Map> first_map() const { return map_set_.at(0); }
UniqueSet<Map> map_set() const { return map_set_; }
+ void set_map_set(UniqueSet<Map>* maps, Zone *zone) {
+ map_set_.Clear();
+ for (int i = 0; i < maps->size(); i++) {
+ map_set_.Add(maps->at(i), zone);
+ }
+ }
+
bool has_migration_target() const {
return has_migration_target_;
}
+ bool is_stable() const {
+ return is_stable_;
+ }
+
DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
protected:
@@ -2689,30 +2753,38 @@ class HCheckMaps V8_FINAL : public HTemplateInstruction<2> {
virtual int RedefinedOperandIndex() { return 0; }
private:
- void Add(Handle<Map> map, Zone* zone) {
+ void Add(Handle<Map> map, CompilationInfo* info, Zone* zone) {
map_set_.Add(Unique<Map>(map), zone);
+ is_stable_ = is_stable_ && map->is_stable();
+ if (is_stable_) {
+ map->AddDependentCompilationInfo(
+ DependentCode::kPrototypeCheckGroup, info);
+ } else {
+ SetDependsOnFlag(kMaps);
+ SetDependsOnFlag(kElementsKind);
+ }
+
if (!has_migration_target_ && map->is_migration_target()) {
has_migration_target_ = true;
- SetGVNFlag(kChangesNewSpacePromotion);
+ SetChangesFlag(kNewSpacePromotion);
}
}
// Clients should use one of the static New* methods above.
HCheckMaps(HValue* value, Zone *zone, HValue* typecheck)
: HTemplateInstruction<2>(value->type()),
- omit_(false), has_migration_target_(false) {
+ omit_(false), has_migration_target_(false), is_stable_(true) {
SetOperandAt(0, value);
// Use the object value for the dependency if NULL is passed.
SetOperandAt(1, typecheck != NULL ? typecheck : value);
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
SetFlag(kTrackSideEffectDominators);
- SetGVNFlag(kDependsOnMaps);
- SetGVNFlag(kDependsOnElementsKind);
}
bool omit_;
bool has_migration_target_;
+ bool is_stable_;
UniqueSet<Map> map_set_;
};
@@ -3147,7 +3219,7 @@ class HPhi V8_FINAL : public HValue {
bool IsReceiver() const { return merged_index_ == 0; }
bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; }
- virtual int position() const V8_OVERRIDE;
+ virtual HSourcePosition position() const V8_OVERRIDE;
int merged_index() const { return merged_index_; }
@@ -3312,7 +3384,7 @@ class HCapturedObject V8_FINAL : public HDematerializedObject {
void ReuseSideEffectsFromStore(HInstruction* store) {
ASSERT(store->HasObservableSideEffects());
ASSERT(store->IsStoreNamedField());
- gvn_flags_.Add(store->gvn_flags());
+ changes_flags_.Add(store->ChangesFlags());
}
// Replay effects of this instruction on the given environment.
@@ -3345,10 +3417,8 @@ class HConstant V8_FINAL : public HTemplateInstruction<0> {
int32_t value,
Representation representation,
HInstruction* instruction) {
- HConstant* new_constant =
- HConstant::New(zone, context, value, representation);
- new_constant->InsertAfter(instruction);
- return new_constant;
+ return instruction->Append(HConstant::New(
+ zone, context, value, representation));
}
static HConstant* CreateAndInsertBefore(Zone* zone,
@@ -3356,21 +3426,17 @@ class HConstant V8_FINAL : public HTemplateInstruction<0> {
int32_t value,
Representation representation,
HInstruction* instruction) {
- HConstant* new_constant =
- HConstant::New(zone, context, value, representation);
- new_constant->InsertBefore(instruction);
- return new_constant;
+ return instruction->Prepend(HConstant::New(
+ zone, context, value, representation));
}
static HConstant* CreateAndInsertBefore(Zone* zone,
Unique<Object> unique,
bool is_not_in_new_space,
HInstruction* instruction) {
- HConstant* new_constant = new(zone) HConstant(unique,
- Representation::Tagged(), HType::Tagged(), false, is_not_in_new_space,
- false, false);
- new_constant->InsertBefore(instruction);
- return new_constant;
+ return instruction->Prepend(new(zone) HConstant(
+ unique, Representation::Tagged(), HType::Tagged(), false,
+ is_not_in_new_space, false, false));
}
Handle<Object> handle(Isolate* isolate) {
@@ -3402,33 +3468,7 @@ class HConstant V8_FINAL : public HTemplateInstruction<0> {
return is_not_in_new_space_;
}
- bool ImmortalImmovable() const {
- if (has_int32_value_) {
- return false;
- }
- if (has_double_value_) {
- if (IsSpecialDouble()) {
- return true;
- }
- return false;
- }
- if (has_external_reference_value_) {
- return false;
- }
-
- ASSERT(!object_.handle().is_null());
- Heap* heap = isolate()->heap();
- ASSERT(!object_.IsKnownGlobal(heap->minus_zero_value()));
- ASSERT(!object_.IsKnownGlobal(heap->nan_value()));
- return
- object_.IsKnownGlobal(heap->undefined_value()) ||
- object_.IsKnownGlobal(heap->null_value()) ||
- object_.IsKnownGlobal(heap->true_value()) ||
- object_.IsKnownGlobal(heap->false_value()) ||
- object_.IsKnownGlobal(heap->the_hole_value()) ||
- object_.IsKnownGlobal(heap->empty_string()) ||
- object_.IsKnownGlobal(heap->empty_fixed_array());
- }
+ bool ImmortalImmovable() const;
bool IsCell() const {
return is_cell_;
@@ -3684,6 +3724,13 @@ class HBinaryOperation : public HTemplateInstruction<3> {
return representation();
}
+ void SetOperandPositions(Zone* zone,
+ HSourcePosition left_pos,
+ HSourcePosition right_pos) {
+ set_operand_position(zone, 1, left_pos);
+ set_operand_position(zone, 2, right_pos);
+ }
+
DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation)
private:
@@ -3698,6 +3745,8 @@ class HWrapReceiver V8_FINAL : public HTemplateInstruction<2> {
public:
DECLARE_INSTRUCTION_FACTORY_P2(HWrapReceiver, HValue*, HValue*);
+ virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
+
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
return Representation::Tagged();
}
@@ -3708,15 +3757,21 @@ class HWrapReceiver V8_FINAL : public HTemplateInstruction<2> {
virtual HValue* Canonicalize() V8_OVERRIDE;
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
+ bool known_function() const { return known_function_; }
DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
private:
HWrapReceiver(HValue* receiver, HValue* function) {
+ known_function_ = function->IsConstant() &&
+ HConstant::cast(function)->handle(function->isolate())->IsJSFunction();
set_representation(Representation::Tagged());
SetOperandAt(0, receiver);
SetOperandAt(1, function);
+ SetFlag(kUseGVN);
}
+
+ bool known_function_;
};
@@ -3893,6 +3948,8 @@ class HBoundsCheck V8_FINAL : public HTemplateInstruction<2> {
protected:
friend class HBoundsCheckBaseIndexInformation;
+ virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
+
virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
bool skip_check_;
HValue* base_;
@@ -3962,7 +4019,7 @@ class HBitwiseBinaryOperation : public HBinaryOperation {
}
virtual void RepresentationChanged(Representation to) V8_OVERRIDE {
- if (to.IsTagged()) SetGVNFlag(kChangesNewSpacePromotion);
+ if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
if (to.IsTagged() &&
(left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
SetAllSideEffects();
@@ -4039,7 +4096,7 @@ class HArithmeticBinaryOperation : public HBinaryOperation {
}
virtual void RepresentationChanged(Representation to) V8_OVERRIDE {
- if (to.IsTagged()) SetGVNFlag(kChangesNewSpacePromotion);
+ if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
if (to.IsTagged() &&
(left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
SetAllSideEffects();
@@ -4050,7 +4107,14 @@ class HArithmeticBinaryOperation : public HBinaryOperation {
}
}
+ bool RightIsPowerOf2() {
+ if (!right()->IsInteger32Constant()) return false;
+ int32_t value = right()->GetInteger32Constant();
+ return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value));
+ }
+
DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)
+
private:
virtual bool IsDeletable() const V8_OVERRIDE { return true; }
};
@@ -4117,6 +4181,13 @@ class HCompareNumericAndBranch : public HTemplateControlInstruction<2, 2> {
}
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
+ void SetOperandPositions(Zone* zone,
+ HSourcePosition left_pos,
+ HSourcePosition right_pos) {
+ set_operand_position(zone, 0, left_pos);
+ set_operand_position(zone, 1, right_pos);
+ }
+
DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)
private:
@@ -4165,6 +4236,28 @@ class HCompareHoleAndBranch V8_FINAL : public HUnaryControlInstruction {
};
+class HCompareMinusZeroAndBranch V8_FINAL : public HUnaryControlInstruction {
+ public:
+ DECLARE_INSTRUCTION_FACTORY_P1(HCompareMinusZeroAndBranch, HValue*);
+
+ virtual void InferRepresentation(
+ HInferRepresentationPhase* h_infer) V8_OVERRIDE;
+
+ virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
+ return representation();
+ }
+
+ virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
+
+ DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch)
+
+ private:
+ explicit HCompareMinusZeroAndBranch(HValue* value)
+ : HUnaryControlInstruction(value, NULL, NULL) {
+ }
+};
+
+
class HCompareObjectEqAndBranch : public HTemplateControlInstruction<2, 2> {
public:
HCompareObjectEqAndBranch(HValue* left,
@@ -4240,6 +4333,9 @@ class HIsStringAndBranch V8_FINAL : public HUnaryControlInstruction {
DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
+ protected:
+ virtual int RedefinedOperandIndex() { return 0; }
+
private:
HIsStringAndBranch(HValue* value,
HBasicBlock* true_target = NULL,
@@ -4262,6 +4358,7 @@ class HIsSmiAndBranch V8_FINAL : public HUnaryControlInstruction {
protected:
virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
+ virtual int RedefinedOperandIndex() { return 0; }
private:
HIsSmiAndBranch(HValue* value,
@@ -4326,7 +4423,7 @@ class HStringCompareAndBranch : public HTemplateControlInstruction<2, 3> {
SetOperandAt(1, left);
SetOperandAt(2, right);
set_representation(Representation::Tagged());
- SetGVNFlag(kChangesNewSpacePromotion);
+ SetChangesFlag(kNewSpacePromotion);
}
Token::Value token_;
@@ -4445,20 +4542,27 @@ class HTypeofIsAndBranch V8_FINAL : public HUnaryControlInstruction {
DECLARE_INSTRUCTION_FACTORY_P2(HTypeofIsAndBranch, HValue*, Handle<String>);
Handle<String> type_literal() { return type_literal_; }
+ bool compares_number_type() { return compares_number_type_; }
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- return Representation::Tagged();
+ return Representation::None();
}
+ virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
+
private:
HTypeofIsAndBranch(HValue* value, Handle<String> type_literal)
: HUnaryControlInstruction(value, NULL, NULL),
- type_literal_(type_literal) { }
+ type_literal_(type_literal) {
+ Heap* heap = type_literal->GetHeap();
+ compares_number_type_ = type_literal->Equals(heap->number_string());
+ }
Handle<String> type_literal_;
+ bool compares_number_type_ : 1;
};
@@ -4544,7 +4648,7 @@ class HPower V8_FINAL : public HTemplateInstruction<2> {
SetOperandAt(1, right);
set_representation(Representation::Double());
SetFlag(kUseGVN);
- SetGVNFlag(kChangesNewSpacePromotion);
+ SetChangesFlag(kNewSpacePromotion);
}
virtual bool IsDeletable() const V8_OVERRIDE {
@@ -4553,28 +4657,6 @@ class HPower V8_FINAL : public HTemplateInstruction<2> {
};
-class HRandom V8_FINAL : public HTemplateInstruction<1> {
- public:
- DECLARE_INSTRUCTION_FACTORY_P1(HRandom, HValue*);
-
- HValue* global_object() { return OperandAt(0); }
-
- virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(Random)
-
- private:
- explicit HRandom(HValue* global_object) {
- SetOperandAt(0, global_object);
- set_representation(Representation::Double());
- }
-
- virtual bool IsDeletable() const V8_OVERRIDE { return true; }
-};
-
-
class HAdd V8_FINAL : public HArithmeticBinaryOperation {
public:
static HInstruction* New(Zone* zone,
@@ -4584,8 +4666,9 @@ class HAdd V8_FINAL : public HArithmeticBinaryOperation {
// Add is only commutative if two integer values are added and not if two
// tagged values are added (because it might be a String concatenation).
+ // We also do not commute (pointer + offset).
virtual bool IsCommutative() const V8_OVERRIDE {
- return !representation().IsTagged();
+ return !representation().IsTagged() && !representation().IsExternal();
}
virtual HValue* EnsureAndPropagateNotMinusZero(
@@ -4607,7 +4690,7 @@ class HAdd V8_FINAL : public HArithmeticBinaryOperation {
virtual void RepresentationChanged(Representation to) V8_OVERRIDE {
if (to.IsTagged()) {
- SetGVNFlag(kChangesNewSpacePromotion);
+ SetChangesFlag(kNewSpacePromotion);
ClearFlag(kAllowUndefinedAsNaN);
}
if (to.IsTagged() &&
@@ -4621,6 +4704,10 @@ class HAdd V8_FINAL : public HArithmeticBinaryOperation {
}
}
+ virtual Representation RepresentationFromInputs() V8_OVERRIDE;
+
+ virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE;
+
DECLARE_CONCRETE_INSTRUCTION(Add)
protected:
@@ -4730,20 +4817,7 @@ class HMod V8_FINAL : public HArithmeticBinaryOperation {
static HInstruction* New(Zone* zone,
HValue* context,
HValue* left,
- HValue* right,
- Maybe<int> fixed_right_arg);
-
- Maybe<int> fixed_right_arg() const { return fixed_right_arg_; }
-
- bool HasPowerOf2Divisor() {
- if (right()->IsConstant() &&
- HConstant::cast(right())->HasInteger32Value()) {
- int32_t value = HConstant::cast(right())->Integer32Value();
- return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value));
- }
-
- return false;
- }
+ HValue* right);
virtual HValue* EnsureAndPropagateNotMinusZero(
BitVector* visited) V8_OVERRIDE;
@@ -4767,15 +4841,10 @@ class HMod V8_FINAL : public HArithmeticBinaryOperation {
private:
HMod(HValue* context,
HValue* left,
- HValue* right,
- Maybe<int> fixed_right_arg)
- : HArithmeticBinaryOperation(context, left, right),
- fixed_right_arg_(fixed_right_arg) {
+ HValue* right) : HArithmeticBinaryOperation(context, left, right) {
SetFlag(kCanBeDivByZero);
SetFlag(kCanOverflow);
}
-
- const Maybe<int> fixed_right_arg_;
};
@@ -4786,15 +4855,6 @@ class HDiv V8_FINAL : public HArithmeticBinaryOperation {
HValue* left,
HValue* right);
- bool HasPowerOf2Divisor() {
- if (right()->IsInteger32Constant()) {
- int32_t value = right()->GetInteger32Constant();
- return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value));
- }
-
- return false;
- }
-
virtual HValue* EnsureAndPropagateNotMinusZero(
BitVector* visited) V8_OVERRIDE;
@@ -5087,8 +5147,8 @@ class HOsrEntry V8_FINAL : public HTemplateInstruction<0> {
private:
explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
- SetGVNFlag(kChangesOsrEntries);
- SetGVNFlag(kChangesNewSpacePromotion);
+ SetChangesFlag(kOsrEntries);
+ SetChangesFlag(kNewSpacePromotion);
}
BailoutId ast_id_;
@@ -5146,13 +5206,6 @@ class HCallStub V8_FINAL : public HUnaryCall {
HValue* context() { return value(); }
- void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
- transcendental_type_ = transcendental_type;
- }
- TranscendentalCache::Type transcendental_type() {
- return transcendental_type_;
- }
-
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
DECLARE_CONCRETE_INSTRUCTION(CallStub)
@@ -5160,12 +5213,10 @@ class HCallStub V8_FINAL : public HUnaryCall {
private:
HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
: HUnaryCall(context, argument_count),
- major_key_(major_key),
- transcendental_type_(TranscendentalCache::kNumberOfCaches) {
+ major_key_(major_key) {
}
CodeStub::Major major_key_;
- TranscendentalCache::Type transcendental_type_;
};
@@ -5239,7 +5290,7 @@ class HLoadGlobalCell V8_FINAL : public HTemplateInstruction<0> {
: cell_(Unique<Cell>::CreateUninitialized(cell)), details_(details) {
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnGlobalVars);
+ SetDependsOnFlag(kGlobalVars);
}
virtual bool IsDeletable() const V8_OVERRIDE { return !RequiresHoleCheck(); }
@@ -5287,14 +5338,22 @@ class HLoadGlobalGeneric V8_FINAL : public HTemplateInstruction<2> {
class HAllocate V8_FINAL : public HTemplateInstruction<2> {
public:
+ static bool CompatibleInstanceTypes(InstanceType type1,
+ InstanceType type2) {
+ return ComputeFlags(TENURED, type1) == ComputeFlags(TENURED, type2) &&
+ ComputeFlags(NOT_TENURED, type1) == ComputeFlags(NOT_TENURED, type2);
+ }
+
static HAllocate* New(Zone* zone,
HValue* context,
HValue* size,
HType type,
PretenureFlag pretenure_flag,
- InstanceType instance_type) {
+ InstanceType instance_type,
+ Handle<AllocationSite> allocation_site =
+ Handle<AllocationSite>::null()) {
return new(zone) HAllocate(context, size, type, pretenure_flag,
- instance_type);
+ instance_type, allocation_site);
}
// Maximum instance size for which allocations will be inlined.
@@ -5343,11 +5402,15 @@ class HAllocate V8_FINAL : public HTemplateInstruction<2> {
flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER);
}
+ bool MustClearNextMapWord() const {
+ return (flags_ & CLEAR_NEXT_MAP_WORD) != 0;
+ }
+
void MakeDoubleAligned() {
flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED);
}
- virtual void HandleSideEffectDominator(GVNFlag side_effect,
+ virtual bool HandleSideEffectDominator(GVNFlag side_effect,
HValue* dominator) V8_OVERRIDE;
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
@@ -5360,30 +5423,45 @@ class HAllocate V8_FINAL : public HTemplateInstruction<2> {
ALLOCATE_IN_OLD_DATA_SPACE = 1 << 1,
ALLOCATE_IN_OLD_POINTER_SPACE = 1 << 2,
ALLOCATE_DOUBLE_ALIGNED = 1 << 3,
- PREFILL_WITH_FILLER = 1 << 4
+ PREFILL_WITH_FILLER = 1 << 4,
+ CLEAR_NEXT_MAP_WORD = 1 << 5
};
HAllocate(HValue* context,
HValue* size,
HType type,
PretenureFlag pretenure_flag,
- InstanceType instance_type)
+ InstanceType instance_type,
+ Handle<AllocationSite> allocation_site =
+ Handle<AllocationSite>::null())
: HTemplateInstruction<2>(type),
+ flags_(ComputeFlags(pretenure_flag, instance_type)),
dominating_allocate_(NULL),
- filler_free_space_size_(NULL),
- clear_next_map_word_(false) {
+ filler_free_space_size_(NULL) {
SetOperandAt(0, context);
SetOperandAt(1, size);
set_representation(Representation::Tagged());
SetFlag(kTrackSideEffectDominators);
- SetGVNFlag(kChangesNewSpacePromotion);
- SetGVNFlag(kDependsOnNewSpacePromotion);
- flags_ = pretenure_flag == TENURED
+ SetChangesFlag(kNewSpacePromotion);
+ SetDependsOnFlag(kNewSpacePromotion);
+
+ if (FLAG_trace_pretenuring) {
+ PrintF("HAllocate with AllocationSite %p %s\n",
+ allocation_site.is_null()
+ ? static_cast<void*>(NULL)
+ : static_cast<void*>(*allocation_site),
+ pretenure_flag == TENURED ? "tenured" : "not tenured");
+ }
+ }
+
+ static Flags ComputeFlags(PretenureFlag pretenure_flag,
+ InstanceType instance_type) {
+ Flags flags = pretenure_flag == TENURED
? (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 = static_cast<Flags>(flags | ALLOCATE_DOUBLE_ALIGNED);
}
// We have to fill the allocated object with one word fillers if we do
// not use allocation folding since some allocations may depend on each
@@ -5391,10 +5469,19 @@ class HAllocate V8_FINAL : public HTemplateInstruction<2> {
// allocations may leave such objects behind in a not completely initialized
// state.
if (!FLAG_use_gvn || !FLAG_use_allocation_folding) {
- flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER);
+ flags = static_cast<Flags>(flags | PREFILL_WITH_FILLER);
}
- clear_next_map_word_ = pretenure_flag == NOT_TENURED &&
- AllocationSite::CanTrack(instance_type);
+ if (pretenure_flag == NOT_TENURED &&
+ AllocationSite::CanTrack(instance_type)) {
+ flags = static_cast<Flags>(flags | CLEAR_NEXT_MAP_WORD);
+ }
+ return flags;
+ }
+
+ void UpdateClearNextMapWord(bool clear_next_map_word) {
+ flags_ = static_cast<Flags>(clear_next_map_word
+ ? flags_ | CLEAR_NEXT_MAP_WORD
+ : flags_ & ~CLEAR_NEXT_MAP_WORD);
}
void UpdateSize(HValue* size) {
@@ -5420,7 +5507,6 @@ class HAllocate V8_FINAL : public HTemplateInstruction<2> {
Handle<Map> known_initial_map_;
HAllocate* dominating_allocate_;
HStoreNamedField* filler_free_space_size_;
- bool clear_next_map_word_;
};
@@ -5450,21 +5536,21 @@ class HStoreCodeEntry V8_FINAL: public HTemplateInstruction<2> {
};
-class HInnerAllocatedObject V8_FINAL: public HTemplateInstruction<1> {
+class HInnerAllocatedObject V8_FINAL : public HTemplateInstruction<2> {
public:
static HInnerAllocatedObject* New(Zone* zone,
HValue* context,
HValue* value,
- int offset,
+ HValue* offset,
HType type = HType::Tagged()) {
return new(zone) HInnerAllocatedObject(value, offset, type);
}
HValue* base_object() { return OperandAt(0); }
- int offset() { return offset_; }
+ HValue* offset() { return OperandAt(1); }
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- return Representation::Tagged();
+ return index == 0 ? Representation::Tagged() : Representation::Integer32();
}
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
@@ -5472,15 +5558,16 @@ class HInnerAllocatedObject V8_FINAL: public HTemplateInstruction<1> {
DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject)
private:
- HInnerAllocatedObject(HValue* value, int offset, HType type = HType::Tagged())
- : HTemplateInstruction<1>(type), offset_(offset) {
+ HInnerAllocatedObject(HValue* value,
+ HValue* offset,
+ HType type = HType::Tagged())
+ : HTemplateInstruction<2>(type) {
ASSERT(value->IsAllocate());
SetOperandAt(0, value);
+ SetOperandAt(1, offset);
set_type(type);
set_representation(Representation::Tagged());
}
-
- int offset_;
};
@@ -5492,11 +5579,10 @@ inline bool StoringValueNeedsWriteBarrier(HValue* value) {
inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
+ HValue* value,
HValue* new_space_dominator) {
- if (object->IsInnerAllocatedObject()) {
- return ReceiverObjectNeedsWriteBarrier(
- HInnerAllocatedObject::cast(object)->base_object(),
- new_space_dominator);
+ while (object->IsInnerAllocatedObject()) {
+ object = HInnerAllocatedObject::cast(object)->base_object();
}
if (object->IsConstant() && HConstant::cast(object)->IsCell()) {
return false;
@@ -5508,7 +5594,17 @@ inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
}
if (object != new_space_dominator) return true;
if (object->IsAllocate()) {
- return !HAllocate::cast(object)->IsNewSpaceAllocation();
+ // Stores to new space allocations require no write barriers if the object
+ // is the new space dominator.
+ if (HAllocate::cast(object)->IsNewSpaceAllocation()) {
+ return false;
+ }
+ // Likewise we don't need a write barrier if we store a value that
+ // originates from the same allocation (via allocation folding).
+ while (value->IsInnerAllocatedObject()) {
+ value = HInnerAllocatedObject::cast(value)->base_object();
+ }
+ return object != value;
}
return true;
}
@@ -5545,7 +5641,7 @@ class HStoreGlobalCell V8_FINAL : public HUnaryOperation {
: HUnaryOperation(value),
cell_(Unique<PropertyCell>::CreateUninitialized(cell)),
details_(details) {
- SetGVNFlag(kChangesGlobalVars);
+ SetChangesFlag(kGlobalVars);
}
Unique<PropertyCell> cell_;
@@ -5553,52 +5649,6 @@ class HStoreGlobalCell V8_FINAL : public HUnaryOperation {
};
-class HStoreGlobalGeneric : public HTemplateInstruction<3> {
- public:
- 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); }
- HValue* global_object() { return OperandAt(1); }
- Handle<Object> name() const { return name_; }
- HValue* value() { return OperandAt(2); }
- StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
-
- virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
-
- virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- return Representation::Tagged();
- }
-
- 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_;
-};
-
-
class HLoadContextSlot V8_FINAL : public HUnaryOperation {
public:
enum Mode {
@@ -5630,7 +5680,7 @@ class HLoadContextSlot V8_FINAL : public HUnaryOperation {
}
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnContextSlots);
+ SetDependsOnFlag(kContextSlots);
}
int slot_index() const { return slot_index_; }
@@ -5714,7 +5764,7 @@ class HStoreContextSlot V8_FINAL : public HTemplateInstruction<2> {
: slot_index_(slot_index), mode_(mode) {
SetOperandAt(0, context);
SetOperandAt(1, value);
- SetGVNFlag(kChangesContextSlots);
+ SetChangesFlag(kContextSlots);
}
int slot_index_;
@@ -5750,8 +5800,19 @@ class HObjectAccess V8_FINAL {
return name_;
}
+ inline bool immutable() const {
+ return ImmutableField::decode(value_);
+ }
+
+ // Returns true if access is being made to an in-object property that
+ // was already added to the object.
+ inline bool existing_inobject_property() const {
+ return ExistingInobjectPropertyField::decode(value_);
+ }
+
inline HObjectAccess WithRepresentation(Representation representation) {
- return HObjectAccess(portion(), offset(), representation, name());
+ return HObjectAccess(portion(), offset(), representation, name(),
+ immutable(), existing_inobject_property());
}
static HObjectAccess ForHeapNumberValue() {
@@ -5792,13 +5853,11 @@ class HObjectAccess V8_FINAL {
? Representation::Smi() : Representation::Tagged());
}
- static HObjectAccess ForAllocationSiteOffset(int offset) {
- ASSERT(offset >= HeapObject::kHeaderSize && offset < AllocationSite::kSize);
- return HObjectAccess(kInobject, offset);
- }
+ static HObjectAccess ForAllocationSiteOffset(int offset);
static HObjectAccess ForAllocationSiteList() {
- return HObjectAccess(kExternalMemory, 0, Representation::Tagged());
+ return HObjectAccess(kExternalMemory, 0, Representation::Tagged(),
+ Handle<String>::null(), false, false);
}
static HObjectAccess ForFixedArrayLength() {
@@ -5808,6 +5867,12 @@ class HObjectAccess V8_FINAL {
FLAG_track_fields ? Representation::Smi() : Representation::Tagged());
}
+ static HObjectAccess ForStringHashField() {
+ return HObjectAccess(kInobject,
+ String::kHashFieldOffset,
+ Representation::Integer32());
+ }
+
static HObjectAccess ForStringLength() {
STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
return HObjectAccess(
@@ -5816,6 +5881,14 @@ class HObjectAccess V8_FINAL {
FLAG_track_fields ? Representation::Smi() : Representation::Tagged());
}
+ static HObjectAccess ForConsStringFirst() {
+ return HObjectAccess(kInobject, ConsString::kFirstOffset);
+ }
+
+ static HObjectAccess ForConsStringSecond() {
+ return HObjectAccess(kInobject, ConsString::kSecondOffset);
+ }
+
static HObjectAccess ForPropertiesPointer() {
return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
}
@@ -5844,6 +5917,10 @@ class HObjectAccess V8_FINAL {
return HObjectAccess(kInobject, SharedFunctionInfo::kFirstContextSlot);
}
+ static HObjectAccess ForFirstOsrAstIdSlot() {
+ return HObjectAccess(kInobject, SharedFunctionInfo::kFirstOsrAstIdSlot);
+ }
+
static HObjectAccess ForOptimizedCodeMap() {
return HObjectAccess(kInobject,
SharedFunctionInfo::kOptimizedCodeMapOffset);
@@ -5860,7 +5937,13 @@ class HObjectAccess V8_FINAL {
static HObjectAccess ForMapInstanceSize() {
return HObjectAccess(kInobject,
Map::kInstanceSizeOffset,
- Representation::Byte());
+ Representation::UInteger8());
+ }
+
+ static HObjectAccess ForMapInstanceType() {
+ return HObjectAccess(kInobject,
+ Map::kInstanceTypeOffset,
+ Representation::UInteger8());
}
static HObjectAccess ForPropertyCellValue() {
@@ -5876,16 +5959,29 @@ class HObjectAccess V8_FINAL {
}
static HObjectAccess ForCounter() {
- return HObjectAccess(kExternalMemory, 0, Representation::Integer32());
+ return HObjectAccess(kExternalMemory, 0, Representation::Integer32(),
+ Handle<String>::null(), false, false);
}
// Create an access to an offset in a fixed array header.
static HObjectAccess ForFixedArrayHeader(int offset);
// Create an access to an in-object property in a JSObject.
- static HObjectAccess ForJSObjectOffset(int offset,
+ // This kind of access must be used when the object |map| is known and
+ // in-object properties are being accessed. Accesses of the in-object
+ // properties can have different semantics depending on whether corresponding
+ // property was added to the map or not.
+ static HObjectAccess ForMapAndOffset(Handle<Map> map, int offset,
Representation representation = Representation::Tagged());
+ // Create an access to an in-object property in a JSObject.
+ // This kind of access can be used for accessing object header fields or
+ // in-object properties if the map of the object is not known.
+ static HObjectAccess ForObservableJSObjectOffset(int offset,
+ Representation representation = Representation::Tagged()) {
+ return ForMapAndOffset(Handle<Map>::null(), offset, representation);
+ }
+
// Create an access to an in-object property in a JSArray.
static HObjectAccess ForJSArrayOffset(int offset);
@@ -5902,14 +5998,58 @@ class HObjectAccess V8_FINAL {
// Create an access for the payload of a Cell or JSGlobalPropertyCell.
static HObjectAccess ForCellPayload(Isolate* isolate);
- void PrintTo(StringStream* stream);
+ static HObjectAccess ForJSTypedArrayLength() {
+ return HObjectAccess::ForObservableJSObjectOffset(
+ JSTypedArray::kLengthOffset);
+ }
+
+ static HObjectAccess ForJSArrayBufferBackingStore() {
+ return HObjectAccess::ForObservableJSObjectOffset(
+ JSArrayBuffer::kBackingStoreOffset, Representation::External());
+ }
+
+ static HObjectAccess ForExternalArrayExternalPointer() {
+ return HObjectAccess::ForObservableJSObjectOffset(
+ ExternalArray::kExternalPointerOffset, Representation::External());
+ }
+
+ static HObjectAccess ForJSArrayBufferViewWeakNext() {
+ return HObjectAccess::ForObservableJSObjectOffset(
+ JSArrayBufferView::kWeakNextOffset);
+ }
+
+ static HObjectAccess ForJSArrayBufferWeakFirstView() {
+ return HObjectAccess::ForObservableJSObjectOffset(
+ JSArrayBuffer::kWeakFirstViewOffset);
+ }
+
+ static HObjectAccess ForJSArrayBufferViewBuffer() {
+ return HObjectAccess::ForObservableJSObjectOffset(
+ JSArrayBufferView::kBufferOffset);
+ }
+
+ static HObjectAccess ForJSArrayBufferViewByteOffset() {
+ return HObjectAccess::ForObservableJSObjectOffset(
+ JSArrayBufferView::kByteOffsetOffset);
+ }
+
+ static HObjectAccess ForJSArrayBufferViewByteLength() {
+ return HObjectAccess::ForObservableJSObjectOffset(
+ JSArrayBufferView::kByteLengthOffset);
+ }
+
+ static HObjectAccess ForGlobalObjectNativeContext() {
+ return HObjectAccess(kInobject, GlobalObject::kNativeContextOffset);
+ }
+
+ void PrintTo(StringStream* stream) const;
inline bool Equals(HObjectAccess that) const {
return value_ == that.value_; // portion and offset must match
}
protected:
- void SetGVNFlags(HValue *instr, bool is_store);
+ void SetGVNFlags(HValue *instr, PropertyAccessType access_type);
private:
// internal use only; different parts of an object or array
@@ -5924,28 +6064,41 @@ class HObjectAccess V8_FINAL {
kExternalMemory // some field in external memory
};
+ HObjectAccess() : value_(0) {}
+
HObjectAccess(Portion portion, int offset,
Representation representation = Representation::Tagged(),
- Handle<String> name = Handle<String>::null())
+ Handle<String> name = Handle<String>::null(),
+ bool immutable = false,
+ bool existing_inobject_property = true)
: value_(PortionField::encode(portion) |
RepresentationField::encode(representation.kind()) |
+ ImmutableField::encode(immutable ? 1 : 0) |
+ ExistingInobjectPropertyField::encode(
+ existing_inobject_property ? 1 : 0) |
OffsetField::encode(offset)),
name_(name) {
// assert that the fields decode correctly
ASSERT(this->offset() == offset);
ASSERT(this->portion() == portion);
+ ASSERT(this->immutable() == immutable);
+ ASSERT(this->existing_inobject_property() == existing_inobject_property);
ASSERT(RepresentationField::decode(value_) == representation.kind());
+ ASSERT(!this->existing_inobject_property() || IsInobject());
}
class PortionField : public BitField<Portion, 0, 3> {};
- class RepresentationField : public BitField<Representation::Kind, 3, 3> {};
- class OffsetField : public BitField<int, 6, 26> {};
+ class RepresentationField : public BitField<Representation::Kind, 3, 4> {};
+ class ImmutableField : public BitField<bool, 7, 1> {};
+ class ExistingInobjectPropertyField : public BitField<bool, 8, 1> {};
+ class OffsetField : public BitField<int, 9, 23> {};
- uint32_t value_; // encodes portion, representation, and offset
+ uint32_t value_; // encodes portion, representation, immutable, and offset
Handle<String> name_;
friend class HLoadNamedField;
friend class HStoreNamedField;
+ friend class SideEffectsTracker;
inline Portion portion() const {
return PortionField::decode(value_);
@@ -5953,12 +6106,17 @@ class HObjectAccess V8_FINAL {
};
-class HLoadNamedField V8_FINAL : public HTemplateInstruction<1> {
+class HLoadNamedField V8_FINAL : public HTemplateInstruction<2> {
public:
- DECLARE_INSTRUCTION_FACTORY_P2(HLoadNamedField, HValue*, HObjectAccess);
+ DECLARE_INSTRUCTION_FACTORY_P3(HLoadNamedField, HValue*, HValue*,
+ HObjectAccess);
HValue* object() { return OperandAt(0); }
- bool HasTypeCheck() { return object()->IsCheckMaps(); }
+ HValue* dependency() {
+ ASSERT(HasDependency());
+ return OperandAt(1);
+ }
+ bool HasDependency() const { return OperandAt(0) != OperandAt(1); }
HObjectAccess access() const { return access_; }
Representation field_representation() const {
return access_.representation();
@@ -5987,16 +6145,26 @@ class HLoadNamedField V8_FINAL : public HTemplateInstruction<1> {
}
private:
- HLoadNamedField(HValue* object, HObjectAccess access) : access_(access) {
+ HLoadNamedField(HValue* object,
+ HValue* dependency,
+ HObjectAccess access) : access_(access) {
ASSERT(object != NULL);
SetOperandAt(0, object);
+ SetOperandAt(1, dependency != NULL ? dependency : object);
Representation representation = access.representation();
- if (representation.IsByte()) {
+ if (representation.IsInteger8() ||
+ representation.IsUInteger8() ||
+ representation.IsInteger16() ||
+ representation.IsUInteger16()) {
set_representation(Representation::Integer32());
} else if (representation.IsSmi()) {
set_type(HType::Smi());
- set_representation(representation);
+ if (SmiValuesAre32Bits()) {
+ set_representation(Representation::Integer32());
+ } else {
+ set_representation(representation);
+ }
} else if (representation.IsDouble() ||
representation.IsExternal() ||
representation.IsInteger32()) {
@@ -6008,7 +6176,7 @@ class HLoadNamedField V8_FINAL : public HTemplateInstruction<1> {
} else {
set_representation(Representation::Tagged());
}
- access.SetGVNFlags(this, false);
+ access.SetGVNFlags(this, LOAD);
}
virtual bool IsDeletable() const V8_OVERRIDE { return true; }
@@ -6067,7 +6235,7 @@ class HLoadFunctionPrototype V8_FINAL : public HUnaryOperation {
: HUnaryOperation(function) {
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnCalls);
+ SetDependsOnFlag(kCalls);
}
};
@@ -6105,6 +6273,12 @@ class HLoadKeyed V8_FINAL
bool is_external() const {
return IsExternalArrayElementsKind(elements_kind());
}
+ bool is_fixed_typed_array() const {
+ return IsFixedTypedArrayElementsKind(elements_kind());
+ }
+ bool is_typed_elements() const {
+ return is_external() || is_fixed_typed_array();
+ }
HValue* elements() { return OperandAt(0); }
HValue* key() { return OperandAt(1); }
HValue* dependency() {
@@ -6133,9 +6307,10 @@ class HLoadKeyed V8_FINAL
}
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- // kind_fast: tagged[int32] (none)
- // kind_double: tagged[int32] (none)
- // kind_external: external[int32] (none)
+ // kind_fast: tagged[int32] (none)
+ // kind_double: tagged[int32] (none)
+ // kind_fixed_typed_array: tagged[int32] (none)
+ // kind_external: external[int32] (none)
if (index == 0) {
return is_external() ? Representation::External()
: Representation::Tagged();
@@ -6185,7 +6360,7 @@ class HLoadKeyed V8_FINAL
SetOperandAt(1, key);
SetOperandAt(2, dependency != NULL ? dependency : obj);
- if (!is_external()) {
+ if (!is_typed_elements()) {
// I can detect the case between storing double (holey and fast) and
// smi/object by looking at elements_kind_.
ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) ||
@@ -6196,27 +6371,39 @@ class HLoadKeyed V8_FINAL
(!IsHoleyElementsKind(elements_kind) ||
mode == NEVER_RETURN_HOLE)) {
set_type(HType::Smi());
- set_representation(Representation::Smi());
+ if (SmiValuesAre32Bits() && !RequiresHoleCheck()) {
+ set_representation(Representation::Integer32());
+ } else {
+ set_representation(Representation::Smi());
+ }
} else {
set_representation(Representation::Tagged());
}
- SetGVNFlag(kDependsOnArrayElements);
+ SetDependsOnFlag(kArrayElements);
} else {
set_representation(Representation::Double());
- SetGVNFlag(kDependsOnDoubleArrayElements);
+ SetDependsOnFlag(kDoubleArrayElements);
}
} else {
- if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
- elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
+ if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+ elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
+ elements_kind == FLOAT32_ELEMENTS ||
+ elements_kind == FLOAT64_ELEMENTS) {
set_representation(Representation::Double());
} else {
set_representation(Representation::Integer32());
}
- SetGVNFlag(kDependsOnExternalMemory);
+ if (is_external()) {
+ SetDependsOnFlag(kExternalMemory);
+ } else if (is_fixed_typed_array()) {
+ SetDependsOnFlag(kTypedArrayElements);
+ } else {
+ UNREACHABLE();
+ }
// Native code could change the specialized array.
- SetGVNFlag(kDependsOnCalls);
+ SetDependsOnFlag(kCalls);
}
SetFlag(kUseGVN);
@@ -6288,10 +6475,23 @@ class HLoadKeyedGeneric V8_FINAL : public HTemplateInstruction<3> {
};
+// Indicates whether the store is a store to an entry that was previously
+// initialized or not.
+enum StoreFieldOrKeyedMode {
+ // The entry could be either previously initialized or not.
+ INITIALIZING_STORE,
+ // At the time of this store it is guaranteed that the entry is already
+ // initialized.
+ STORE_TO_INITIALIZED_ENTRY
+};
+
+
class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> {
public:
DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*,
HObjectAccess, HValue*);
+ DECLARE_INSTRUCTION_FACTORY_P4(HStoreNamedField, HValue*,
+ HObjectAccess, HValue*, StoreFieldOrKeyedMode);
DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
@@ -6306,20 +6506,31 @@ class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> {
// object must be external in case of external memory access
return Representation::External();
} else if (index == 1) {
- if (field_representation().IsByte() ||
+ if (field_representation().IsInteger8() ||
+ field_representation().IsUInteger8() ||
+ field_representation().IsInteger16() ||
+ field_representation().IsUInteger16() ||
field_representation().IsInteger32()) {
return Representation::Integer32();
- } else if (field_representation().IsDouble() ||
- field_representation().IsSmi()) {
+ } else if (field_representation().IsDouble()) {
return field_representation();
+ } else if (field_representation().IsSmi()) {
+ if (SmiValuesAre32Bits() && store_mode_ == STORE_TO_INITIALIZED_ENTRY) {
+ return Representation::Integer32();
+ }
+ return field_representation();
+ } else if (field_representation().IsExternal()) {
+ return Representation::External();
}
}
return Representation::Tagged();
}
- virtual void HandleSideEffectDominator(GVNFlag side_effect,
+ virtual bool HandleSideEffectDominator(GVNFlag side_effect,
HValue* dominator) V8_OVERRIDE {
- ASSERT(side_effect == kChangesNewSpacePromotion);
+ ASSERT(side_effect == kNewSpacePromotion);
+ if (!FLAG_use_write_barrier_elimination) return false;
new_space_dominator_ = dominator;
+ return false;
}
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
@@ -6335,6 +6546,7 @@ class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> {
HObjectAccess access() const { return access_; }
HValue* new_space_dominator() const { return new_space_dominator_; }
bool has_transition() const { return has_transition_; }
+ StoreFieldOrKeyedMode store_mode() const { return store_mode_; }
Handle<Map> transition_map() const {
if (has_transition()) {
@@ -6353,6 +6565,16 @@ class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> {
}
SetOperandAt(2, map_constant);
has_transition_ = true;
+ is_stable_ = map->is_stable();
+
+ if (is_stable_) {
+ map->AddDependentCompilationInfo(
+ DependentCode::kPrototypeCheckGroup, info);
+ }
+ }
+
+ bool is_stable() const {
+ return is_stable_;
}
bool NeedsWriteBarrier() {
@@ -6364,12 +6586,14 @@ class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> {
if (field_representation().IsInteger32()) return false;
if (field_representation().IsExternal()) return false;
return StoringValueNeedsWriteBarrier(value()) &&
- ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
+ ReceiverObjectNeedsWriteBarrier(object(), value(),
+ new_space_dominator());
}
bool NeedsWriteBarrierForMap() {
if (IsSkipWriteBarrier()) return false;
- return ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
+ return ReceiverObjectNeedsWriteBarrier(object(), transition(),
+ new_space_dominator());
}
Representation field_representation() const {
@@ -6383,21 +6607,30 @@ class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> {
private:
HStoreNamedField(HValue* obj,
HObjectAccess access,
- HValue* val)
+ HValue* val,
+ StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE)
: access_(access),
new_space_dominator_(NULL),
write_barrier_mode_(UPDATE_WRITE_BARRIER),
- has_transition_(false) {
+ has_transition_(false),
+ is_stable_(false),
+ store_mode_(store_mode) {
+ // Stores to a non existing in-object property are allowed only to the
+ // newly allocated objects (via HAllocate or HInnerAllocatedObject).
+ ASSERT(!access.IsInobject() || access.existing_inobject_property() ||
+ obj->IsAllocate() || obj->IsInnerAllocatedObject());
SetOperandAt(0, obj);
SetOperandAt(1, val);
SetOperandAt(2, obj);
- access.SetGVNFlags(this, true);
+ access.SetGVNFlags(this, STORE);
}
HObjectAccess access_;
HValue* new_space_dominator_;
WriteBarrierMode write_barrier_mode_ : 1;
bool has_transition_ : 1;
+ bool is_stable_ : 1;
+ StoreFieldOrKeyedMode store_mode_ : 1;
};
@@ -6444,12 +6677,15 @@ class HStoreKeyed V8_FINAL
public:
DECLARE_INSTRUCTION_FACTORY_P4(HStoreKeyed, HValue*, HValue*, HValue*,
ElementsKind);
+ DECLARE_INSTRUCTION_FACTORY_P5(HStoreKeyed, HValue*, HValue*, HValue*,
+ ElementsKind, StoreFieldOrKeyedMode);
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- // kind_fast: tagged[int32] = tagged
- // kind_double: tagged[int32] = double
- // kind_smi : tagged[int32] = smi
- // kind_external: external[int32] = (double | int32)
+ // kind_fast: tagged[int32] = tagged
+ // kind_double: tagged[int32] = double
+ // kind_smi : tagged[int32] = smi
+ // kind_fixed_typed_array: tagged[int32] = (double | int32)
+ // kind_external: external[int32] = (double | int32)
if (index == 0) {
return is_external() ? Representation::External()
: Representation::Tagged();
@@ -6462,31 +6698,45 @@ class HStoreKeyed V8_FINAL
if (IsDoubleOrFloatElementsKind(elements_kind())) {
return Representation::Double();
}
-
+ if (SmiValuesAre32Bits() && store_mode_ == STORE_TO_INITIALIZED_ENTRY) {
+ return Representation::Integer32();
+ }
if (IsFastSmiElementsKind(elements_kind())) {
return Representation::Smi();
}
- return is_external() ? Representation::Integer32()
- : Representation::Tagged();
+ return is_external() || is_fixed_typed_array()
+ ? Representation::Integer32()
+ : Representation::Tagged();
}
bool is_external() const {
return IsExternalArrayElementsKind(elements_kind());
}
+ bool is_fixed_typed_array() const {
+ return IsFixedTypedArrayElementsKind(elements_kind());
+ }
+
+ bool is_typed_elements() const {
+ return is_external() || is_fixed_typed_array();
+ }
+
virtual Representation observed_input_representation(int index) V8_OVERRIDE {
if (index < 2) return RequiredInputRepresentation(index);
if (IsUninitialized()) {
return Representation::None();
}
- if (IsFastSmiElementsKind(elements_kind())) {
- return Representation::Smi();
- }
if (IsDoubleOrFloatElementsKind(elements_kind())) {
return Representation::Double();
}
- if (is_external()) {
+ if (SmiValuesAre32Bits() && store_mode_ == STORE_TO_INITIALIZED_ENTRY) {
+ return Representation::Integer32();
+ }
+ if (IsFastSmiElementsKind(elements_kind())) {
+ return Representation::Smi();
+ }
+ if (is_typed_elements()) {
return Representation::Integer32();
}
// For fast object elements kinds, don't assume anything.
@@ -6499,6 +6749,7 @@ class HStoreKeyed V8_FINAL
bool value_is_smi() const {
return IsFastSmiElementsKind(elements_kind_);
}
+ StoreFieldOrKeyedMode store_mode() const { return store_mode_; }
ElementsKind elements_kind() const { return elements_kind_; }
uint32_t index_offset() { return index_offset_; }
void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
@@ -6518,10 +6769,11 @@ class HStoreKeyed V8_FINAL
return value()->IsConstant() && HConstant::cast(value())->IsTheHole();
}
- virtual void HandleSideEffectDominator(GVNFlag side_effect,
+ virtual bool HandleSideEffectDominator(GVNFlag side_effect,
HValue* dominator) V8_OVERRIDE {
- ASSERT(side_effect == kChangesNewSpacePromotion);
+ ASSERT(side_effect == kNewSpacePromotion);
new_space_dominator_ = dominator;
+ return false;
}
HValue* new_space_dominator() const { return new_space_dominator_; }
@@ -6531,7 +6783,8 @@ class HStoreKeyed V8_FINAL
return false;
} else {
return StoringValueNeedsWriteBarrier(value()) &&
- ReceiverObjectNeedsWriteBarrier(elements(), new_space_dominator());
+ ReceiverObjectNeedsWriteBarrier(elements(), value(),
+ new_space_dominator());
}
}
@@ -6543,34 +6796,44 @@ class HStoreKeyed V8_FINAL
private:
HStoreKeyed(HValue* obj, HValue* key, HValue* val,
- ElementsKind elements_kind)
+ ElementsKind elements_kind,
+ StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE)
: elements_kind_(elements_kind),
index_offset_(0),
is_dehoisted_(false),
is_uninitialized_(false),
+ store_mode_(store_mode),
new_space_dominator_(NULL) {
SetOperandAt(0, obj);
SetOperandAt(1, key);
SetOperandAt(2, val);
+ ASSERT(store_mode != STORE_TO_INITIALIZED_ENTRY ||
+ elements_kind == FAST_SMI_ELEMENTS);
+
if (IsFastObjectElementsKind(elements_kind)) {
SetFlag(kTrackSideEffectDominators);
- SetGVNFlag(kDependsOnNewSpacePromotion);
+ SetDependsOnFlag(kNewSpacePromotion);
}
if (is_external()) {
- SetGVNFlag(kChangesExternalMemory);
+ SetChangesFlag(kExternalMemory);
SetFlag(kAllowUndefinedAsNaN);
} else if (IsFastDoubleElementsKind(elements_kind)) {
- SetGVNFlag(kChangesDoubleArrayElements);
+ SetChangesFlag(kDoubleArrayElements);
} else if (IsFastSmiElementsKind(elements_kind)) {
- SetGVNFlag(kChangesArrayElements);
+ SetChangesFlag(kArrayElements);
+ } else if (is_fixed_typed_array()) {
+ SetChangesFlag(kTypedArrayElements);
+ SetFlag(kAllowUndefinedAsNaN);
} else {
- SetGVNFlag(kChangesArrayElements);
+ SetChangesFlag(kArrayElements);
}
// EXTERNAL_{UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
- if (elements_kind >= EXTERNAL_BYTE_ELEMENTS &&
- elements_kind <= EXTERNAL_UNSIGNED_INT_ELEMENTS) {
+ if ((elements_kind >= EXTERNAL_INT8_ELEMENTS &&
+ elements_kind <= EXTERNAL_UINT32_ELEMENTS) ||
+ (elements_kind >= UINT8_ELEMENTS &&
+ elements_kind <= INT32_ELEMENTS)) {
SetFlag(kTruncatingToInt32);
}
}
@@ -6579,6 +6842,7 @@ class HStoreKeyed V8_FINAL
uint32_t index_offset_;
bool is_dehoisted_ : 1;
bool is_uninitialized_ : 1;
+ StoreFieldOrKeyedMode store_mode_: 1;
HValue* new_space_dominator_;
};
@@ -6666,10 +6930,10 @@ class HTransitionElementsKind V8_FINAL : public HTemplateInstruction<2> {
SetOperandAt(0, object);
SetOperandAt(1, context);
SetFlag(kUseGVN);
- SetGVNFlag(kChangesElementsKind);
+ SetChangesFlag(kElementsKind);
if (!IsSimpleMapChangeTransition(from_kind_, to_kind_)) {
- SetGVNFlag(kChangesElementsPointer);
- SetGVNFlag(kChangesNewSpacePromotion);
+ SetChangesFlag(kElementsPointer);
+ SetChangesFlag(kNewSpacePromotion);
}
set_representation(Representation::Tagged());
}
@@ -6687,45 +6951,55 @@ class HStringAdd V8_FINAL : public HBinaryOperation {
HValue* context,
HValue* left,
HValue* right,
- StringAddFlags flags = STRING_ADD_CHECK_NONE);
+ PretenureFlag pretenure_flag = NOT_TENURED,
+ StringAddFlags flags = STRING_ADD_CHECK_BOTH,
+ Handle<AllocationSite> allocation_site =
+ Handle<AllocationSite>::null());
StringAddFlags flags() const { return flags_; }
+ PretenureFlag pretenure_flag() const { return pretenure_flag_; }
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
return Representation::Tagged();
}
+ virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
+
DECLARE_CONCRETE_INSTRUCTION(StringAdd)
protected:
- virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
+ virtual bool DataEquals(HValue* other) V8_OVERRIDE {
+ return flags_ == HStringAdd::cast(other)->flags_ &&
+ pretenure_flag_ == HStringAdd::cast(other)->pretenure_flag_;
+ }
private:
- HStringAdd(HValue* context, HValue* left, HValue* right, StringAddFlags flags)
- : HBinaryOperation(context, left, right, HType::String()), flags_(flags) {
+ HStringAdd(HValue* context,
+ HValue* left,
+ HValue* right,
+ PretenureFlag pretenure_flag,
+ StringAddFlags flags,
+ Handle<AllocationSite> allocation_site)
+ : HBinaryOperation(context, left, right, HType::String()),
+ flags_(flags), pretenure_flag_(pretenure_flag) {
set_representation(Representation::Tagged());
- if (MightHaveSideEffects()) {
- SetAllSideEffects();
- } else {
- SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnMaps);
- SetGVNFlag(kChangesNewSpacePromotion);
+ SetFlag(kUseGVN);
+ SetDependsOnFlag(kMaps);
+ SetChangesFlag(kNewSpacePromotion);
+ if (FLAG_trace_pretenuring) {
+ PrintF("HStringAdd with AllocationSite %p %s\n",
+ allocation_site.is_null()
+ ? static_cast<void*>(NULL)
+ : static_cast<void*>(*allocation_site),
+ pretenure_flag == TENURED ? "tenured" : "not tenured");
}
}
- bool MightHaveSideEffects() const {
- return flags_ != STRING_ADD_CHECK_NONE &&
- (left()->ToStringCanBeObserved() || right()->ToStringCanBeObserved());
- }
-
// No side-effects except possible allocation:
- // NOTE: this instruction does not call ToString() on its inputs, when flags_
- // is set to STRING_ADD_CHECK_NONE.
- virtual bool IsDeletable() const V8_OVERRIDE {
- return !MightHaveSideEffects();
- }
+ virtual bool IsDeletable() const V8_OVERRIDE { return true; }
const StringAddFlags flags_;
+ const PretenureFlag pretenure_flag_;
};
@@ -6762,8 +7036,9 @@ class HStringCharCodeAt V8_FINAL : public HTemplateInstruction<3> {
SetOperandAt(2, index);
set_representation(Representation::Integer32());
SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnMaps);
- SetGVNFlag(kChangesNewSpacePromotion);
+ SetDependsOnFlag(kMaps);
+ SetDependsOnFlag(kStringChars);
+ SetChangesFlag(kNewSpacePromotion);
}
// No side effects: runtime function assumes string + number inputs.
@@ -6797,7 +7072,7 @@ class HStringCharFromCode V8_FINAL : public HTemplateInstruction<2> {
SetOperandAt(1, char_code);
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
- SetGVNFlag(kChangesNewSpacePromotion);
+ SetChangesFlag(kNewSpacePromotion);
}
virtual bool IsDeletable() const V8_OVERRIDE {
@@ -6906,7 +7181,7 @@ class HFunctionLiteral V8_FINAL : public HTemplateInstruction<1> {
language_mode_(shared->language_mode()) {
SetOperandAt(0, context);
set_representation(Representation::Tagged());
- SetGVNFlag(kChangesNewSpacePromotion);
+ SetChangesFlag(kNewSpacePromotion);
}
virtual bool IsDeletable() const V8_OVERRIDE { return true; }
@@ -6977,7 +7252,7 @@ class HToFastProperties V8_FINAL : public HUnaryOperation {
private:
explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
set_representation(Representation::Tagged());
- SetGVNFlag(kChangesNewSpacePromotion);
+ SetChangesFlag(kNewSpacePromotion);
// This instruction is not marked as kChangesMaps, but does
// change the map of the input operand. Use it only when creating
@@ -6993,73 +7268,109 @@ class HToFastProperties V8_FINAL : public HUnaryOperation {
};
-class HValueOf V8_FINAL : public HUnaryOperation {
+class HDateField V8_FINAL : public HUnaryOperation {
public:
- DECLARE_INSTRUCTION_FACTORY_P1(HValueOf, HValue*);
+ DECLARE_INSTRUCTION_FACTORY_P2(HDateField, HValue*, Smi*);
+
+ Smi* index() const { return index_; }
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
return Representation::Tagged();
}
- DECLARE_CONCRETE_INSTRUCTION(ValueOf)
+ DECLARE_CONCRETE_INSTRUCTION(DateField)
private:
- explicit HValueOf(HValue* value) : HUnaryOperation(value) {
+ HDateField(HValue* date, Smi* index)
+ : HUnaryOperation(date), index_(index) {
set_representation(Representation::Tagged());
}
- virtual bool IsDeletable() const V8_OVERRIDE { return true; }
+ Smi* index_;
};
-class HDateField V8_FINAL : public HUnaryOperation {
+class HSeqStringGetChar V8_FINAL : public HTemplateInstruction<2> {
public:
- DECLARE_INSTRUCTION_FACTORY_P2(HDateField, HValue*, Smi*);
-
- Smi* index() const { return index_; }
+ static HInstruction* New(Zone* zone,
+ HValue* context,
+ String::Encoding encoding,
+ HValue* string,
+ HValue* index);
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- return Representation::Tagged();
+ return (index == 0) ? Representation::Tagged()
+ : Representation::Integer32();
}
- DECLARE_CONCRETE_INSTRUCTION(DateField)
+ String::Encoding encoding() const { return encoding_; }
+ HValue* string() const { return OperandAt(0); }
+ HValue* index() const { return OperandAt(1); }
+
+ DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar)
+
+ protected:
+ virtual bool DataEquals(HValue* other) V8_OVERRIDE {
+ return encoding() == HSeqStringGetChar::cast(other)->encoding();
+ }
+
+ virtual Range* InferRange(Zone* zone) V8_OVERRIDE {
+ if (encoding() == String::ONE_BYTE_ENCODING) {
+ return new(zone) Range(0, String::kMaxOneByteCharCode);
+ } else {
+ ASSERT_EQ(String::TWO_BYTE_ENCODING, encoding());
+ return new(zone) Range(0, String::kMaxUtf16CodeUnit);
+ }
+ }
private:
- HDateField(HValue* date, Smi* index)
- : HUnaryOperation(date), index_(index) {
- set_representation(Representation::Tagged());
+ HSeqStringGetChar(String::Encoding encoding,
+ HValue* string,
+ HValue* index) : encoding_(encoding) {
+ SetOperandAt(0, string);
+ SetOperandAt(1, index);
+ set_representation(Representation::Integer32());
+ SetFlag(kUseGVN);
+ SetDependsOnFlag(kStringChars);
}
- Smi* index_;
+ virtual bool IsDeletable() const V8_OVERRIDE { return true; }
+
+ String::Encoding encoding_;
};
-class HSeqStringSetChar V8_FINAL : public HTemplateInstruction<3> {
+class HSeqStringSetChar V8_FINAL : public HTemplateInstruction<4> {
public:
- DECLARE_INSTRUCTION_FACTORY_P4(HSeqStringSetChar, String::Encoding,
- HValue*, HValue*, HValue*);
+ DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(
+ HSeqStringSetChar, String::Encoding,
+ HValue*, HValue*, HValue*);
String::Encoding encoding() { return encoding_; }
- HValue* string() { return OperandAt(0); }
- HValue* index() { return OperandAt(1); }
- HValue* value() { return OperandAt(2); }
+ HValue* context() { return OperandAt(0); }
+ HValue* string() { return OperandAt(1); }
+ HValue* index() { return OperandAt(2); }
+ HValue* value() { return OperandAt(3); }
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- return (index == 0) ? Representation::Tagged()
+ return (index <= 1) ? Representation::Tagged()
: Representation::Integer32();
}
DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar)
private:
- HSeqStringSetChar(String::Encoding encoding,
+ HSeqStringSetChar(HValue* context,
+ String::Encoding encoding,
HValue* string,
HValue* index,
HValue* value) : encoding_(encoding) {
- SetOperandAt(0, string);
- SetOperandAt(1, index);
- SetOperandAt(2, value);
+ SetOperandAt(0, context);
+ SetOperandAt(1, string);
+ SetOperandAt(2, index);
+ SetOperandAt(3, value);
set_representation(Representation::Tagged());
+ SetChangesFlag(kStringChars);
}
String::Encoding encoding_;
@@ -7086,6 +7397,8 @@ class HCheckMapValue V8_FINAL : public HTemplateInstruction<2> {
DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
protected:
+ virtual int RedefinedOperandIndex() { return 0; }
+
virtual bool DataEquals(HValue* other) V8_OVERRIDE {
return true;
}
@@ -7097,8 +7410,8 @@ class HCheckMapValue V8_FINAL : public HTemplateInstruction<2> {
SetOperandAt(1, map);
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
- SetGVNFlag(kDependsOnMaps);
- SetGVNFlag(kDependsOnElementsKind);
+ SetDependsOnFlag(kMaps);
+ SetDependsOnFlag(kElementsKind);
}
};