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

Side by Side Diff: src/hydrogen-instructions.h

Issue 1405363003: Move Hydrogen and Lithium to src/crankshaft/ (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebased Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/hydrogen-infer-types.cc ('k') | src/hydrogen-instructions.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_HYDROGEN_INSTRUCTIONS_H_
6 #define V8_HYDROGEN_INSTRUCTIONS_H_
7
8 #include <cstring>
9 #include <iosfwd>
10
11 #include "src/allocation.h"
12 #include "src/base/bits.h"
13 #include "src/bit-vector.h"
14 #include "src/code-stubs.h"
15 #include "src/conversions.h"
16 #include "src/deoptimizer.h"
17 #include "src/hydrogen-types.h"
18 #include "src/small-pointer-list.h"
19 #include "src/unique.h"
20 #include "src/utils.h"
21 #include "src/zone.h"
22
23 namespace v8 {
24 namespace internal {
25
26 // Forward declarations.
27 struct ChangesOf;
28 class HBasicBlock;
29 class HDiv;
30 class HEnvironment;
31 class HInferRepresentationPhase;
32 class HInstruction;
33 class HLoopInformation;
34 class HStoreNamedField;
35 class HValue;
36 class LInstruction;
37 class LChunkBuilder;
38
39 #define HYDROGEN_ABSTRACT_INSTRUCTION_LIST(V) \
40 V(ArithmeticBinaryOperation) \
41 V(BinaryOperation) \
42 V(BitwiseBinaryOperation) \
43 V(ControlInstruction) \
44 V(Instruction)
45
46
47 #define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
48 V(AbnormalExit) \
49 V(AccessArgumentsAt) \
50 V(Add) \
51 V(AllocateBlockContext) \
52 V(Allocate) \
53 V(ApplyArguments) \
54 V(ArgumentsElements) \
55 V(ArgumentsLength) \
56 V(ArgumentsObject) \
57 V(Bitwise) \
58 V(BlockEntry) \
59 V(BoundsCheck) \
60 V(BoundsCheckBaseIndexInformation) \
61 V(Branch) \
62 V(CallWithDescriptor) \
63 V(CallJSFunction) \
64 V(CallFunction) \
65 V(CallNew) \
66 V(CallNewArray) \
67 V(CallRuntime) \
68 V(CallStub) \
69 V(CapturedObject) \
70 V(Change) \
71 V(CheckArrayBufferNotNeutered) \
72 V(CheckHeapObject) \
73 V(CheckInstanceType) \
74 V(CheckMaps) \
75 V(CheckMapValue) \
76 V(CheckSmi) \
77 V(CheckValue) \
78 V(ClampToUint8) \
79 V(ClassOfTestAndBranch) \
80 V(CompareNumericAndBranch) \
81 V(CompareHoleAndBranch) \
82 V(CompareGeneric) \
83 V(CompareMinusZeroAndBranch) \
84 V(CompareObjectEqAndBranch) \
85 V(CompareMap) \
86 V(Constant) \
87 V(ConstructDouble) \
88 V(Context) \
89 V(DateField) \
90 V(DebugBreak) \
91 V(DeclareGlobals) \
92 V(Deoptimize) \
93 V(Div) \
94 V(DoubleBits) \
95 V(DummyUse) \
96 V(EnterInlined) \
97 V(EnvironmentMarker) \
98 V(ForceRepresentation) \
99 V(ForInCacheArray) \
100 V(ForInPrepareMap) \
101 V(GetCachedArrayIndex) \
102 V(Goto) \
103 V(HasCachedArrayIndexAndBranch) \
104 V(HasInstanceTypeAndBranch) \
105 V(InnerAllocatedObject) \
106 V(InstanceOf) \
107 V(InvokeFunction) \
108 V(IsConstructCallAndBranch) \
109 V(HasInPrototypeChainAndBranch) \
110 V(IsStringAndBranch) \
111 V(IsSmiAndBranch) \
112 V(IsUndetectableAndBranch) \
113 V(LeaveInlined) \
114 V(LoadContextSlot) \
115 V(LoadFieldByIndex) \
116 V(LoadFunctionPrototype) \
117 V(LoadGlobalGeneric) \
118 V(LoadGlobalViaContext) \
119 V(LoadKeyed) \
120 V(LoadKeyedGeneric) \
121 V(LoadNamedField) \
122 V(LoadNamedGeneric) \
123 V(LoadRoot) \
124 V(MapEnumLength) \
125 V(MathFloorOfDiv) \
126 V(MathMinMax) \
127 V(MaybeGrowElements) \
128 V(Mod) \
129 V(Mul) \
130 V(OsrEntry) \
131 V(Parameter) \
132 V(Power) \
133 V(Prologue) \
134 V(PushArguments) \
135 V(RegExpLiteral) \
136 V(Return) \
137 V(Ror) \
138 V(Sar) \
139 V(SeqStringGetChar) \
140 V(SeqStringSetChar) \
141 V(Shl) \
142 V(Shr) \
143 V(Simulate) \
144 V(StackCheck) \
145 V(StoreCodeEntry) \
146 V(StoreContextSlot) \
147 V(StoreFrameContext) \
148 V(StoreGlobalViaContext) \
149 V(StoreKeyed) \
150 V(StoreKeyedGeneric) \
151 V(StoreNamedField) \
152 V(StoreNamedGeneric) \
153 V(StringAdd) \
154 V(StringCharCodeAt) \
155 V(StringCharFromCode) \
156 V(StringCompareAndBranch) \
157 V(Sub) \
158 V(ThisFunction) \
159 V(ToFastProperties) \
160 V(TransitionElementsKind) \
161 V(TrapAllocationMemento) \
162 V(Typeof) \
163 V(TypeofIsAndBranch) \
164 V(UnaryMathOperation) \
165 V(UnknownOSRValue) \
166 V(UseConst) \
167 V(WrapReceiver)
168
169 #define GVN_TRACKED_FLAG_LIST(V) \
170 V(NewSpacePromotion)
171
172 #define GVN_UNTRACKED_FLAG_LIST(V) \
173 V(ArrayElements) \
174 V(ArrayLengths) \
175 V(StringLengths) \
176 V(BackingStoreFields) \
177 V(Calls) \
178 V(ContextSlots) \
179 V(DoubleArrayElements) \
180 V(DoubleFields) \
181 V(ElementsKind) \
182 V(ElementsPointer) \
183 V(GlobalVars) \
184 V(InobjectFields) \
185 V(Maps) \
186 V(OsrEntries) \
187 V(ExternalMemory) \
188 V(StringChars) \
189 V(TypedArrayElements)
190
191
192 #define DECLARE_ABSTRACT_INSTRUCTION(type) \
193 bool Is##type() const final { return true; } \
194 static H##type* cast(HValue* value) { \
195 DCHECK(value->Is##type()); \
196 return reinterpret_cast<H##type*>(value); \
197 }
198
199
200 #define DECLARE_CONCRETE_INSTRUCTION(type) \
201 LInstruction* CompileToLithium(LChunkBuilder* builder) final; \
202 static H##type* cast(HValue* value) { \
203 DCHECK(value->Is##type()); \
204 return reinterpret_cast<H##type*>(value); \
205 } \
206 Opcode opcode() const final { return HValue::k##type; }
207
208
209 enum PropertyAccessType { LOAD, STORE };
210
211
212 class Range final : public ZoneObject {
213 public:
214 Range()
215 : lower_(kMinInt),
216 upper_(kMaxInt),
217 next_(NULL),
218 can_be_minus_zero_(false) { }
219
220 Range(int32_t lower, int32_t upper)
221 : lower_(lower),
222 upper_(upper),
223 next_(NULL),
224 can_be_minus_zero_(false) { }
225
226 int32_t upper() const { return upper_; }
227 int32_t lower() const { return lower_; }
228 Range* next() const { return next_; }
229 Range* CopyClearLower(Zone* zone) const {
230 return new(zone) Range(kMinInt, upper_);
231 }
232 Range* CopyClearUpper(Zone* zone) const {
233 return new(zone) Range(lower_, kMaxInt);
234 }
235 Range* Copy(Zone* zone) const {
236 Range* result = new(zone) Range(lower_, upper_);
237 result->set_can_be_minus_zero(CanBeMinusZero());
238 return result;
239 }
240 int32_t Mask() const;
241 void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
242 bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
243 bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
244 bool CanBeNegative() const { return lower_ < 0; }
245 bool CanBePositive() const { return upper_ > 0; }
246 bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
247 bool IsMostGeneric() const {
248 return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
249 }
250 bool IsInSmiRange() const {
251 return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
252 }
253 void ClampToSmi() {
254 lower_ = Max(lower_, Smi::kMinValue);
255 upper_ = Min(upper_, Smi::kMaxValue);
256 }
257 void KeepOrder();
258 #ifdef DEBUG
259 void Verify() const;
260 #endif
261
262 void StackUpon(Range* other) {
263 Intersect(other);
264 next_ = other;
265 }
266
267 void Intersect(Range* other);
268 void Union(Range* other);
269 void CombinedMax(Range* other);
270 void CombinedMin(Range* other);
271
272 void AddConstant(int32_t value);
273 void Sar(int32_t value);
274 void Shl(int32_t value);
275 bool AddAndCheckOverflow(const Representation& r, Range* other);
276 bool SubAndCheckOverflow(const Representation& r, Range* other);
277 bool MulAndCheckOverflow(const Representation& r, Range* other);
278
279 private:
280 int32_t lower_;
281 int32_t upper_;
282 Range* next_;
283 bool can_be_minus_zero_;
284 };
285
286
287 class HUseListNode: public ZoneObject {
288 public:
289 HUseListNode(HValue* value, int index, HUseListNode* tail)
290 : tail_(tail), value_(value), index_(index) {
291 }
292
293 HUseListNode* tail();
294 HValue* value() const { return value_; }
295 int index() const { return index_; }
296
297 void set_tail(HUseListNode* list) { tail_ = list; }
298
299 #ifdef DEBUG
300 void Zap() {
301 tail_ = reinterpret_cast<HUseListNode*>(1);
302 value_ = NULL;
303 index_ = -1;
304 }
305 #endif
306
307 private:
308 HUseListNode* tail_;
309 HValue* value_;
310 int index_;
311 };
312
313
314 // We reuse use list nodes behind the scenes as uses are added and deleted.
315 // This class is the safe way to iterate uses while deleting them.
316 class HUseIterator final BASE_EMBEDDED {
317 public:
318 bool Done() { return current_ == NULL; }
319 void Advance();
320
321 HValue* value() {
322 DCHECK(!Done());
323 return value_;
324 }
325
326 int index() {
327 DCHECK(!Done());
328 return index_;
329 }
330
331 private:
332 explicit HUseIterator(HUseListNode* head);
333
334 HUseListNode* current_;
335 HUseListNode* next_;
336 HValue* value_;
337 int index_;
338
339 friend class HValue;
340 };
341
342
343 // All tracked flags should appear before untracked ones.
344 enum GVNFlag {
345 // Declare global value numbering flags.
346 #define DECLARE_FLAG(Type) k##Type,
347 GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
348 GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
349 #undef DECLARE_FLAG
350 #define COUNT_FLAG(Type) + 1
351 kNumberOfTrackedSideEffects = 0 GVN_TRACKED_FLAG_LIST(COUNT_FLAG),
352 kNumberOfUntrackedSideEffects = 0 GVN_UNTRACKED_FLAG_LIST(COUNT_FLAG),
353 #undef COUNT_FLAG
354 kNumberOfFlags = kNumberOfTrackedSideEffects + kNumberOfUntrackedSideEffects
355 };
356
357
358 static inline GVNFlag GVNFlagFromInt(int i) {
359 DCHECK(i >= 0);
360 DCHECK(i < kNumberOfFlags);
361 return static_cast<GVNFlag>(i);
362 }
363
364
365 class DecompositionResult final BASE_EMBEDDED {
366 public:
367 DecompositionResult() : base_(NULL), offset_(0), scale_(0) {}
368
369 HValue* base() { return base_; }
370 int offset() { return offset_; }
371 int scale() { return scale_; }
372
373 bool Apply(HValue* other_base, int other_offset, int other_scale = 0) {
374 if (base_ == NULL) {
375 base_ = other_base;
376 offset_ = other_offset;
377 scale_ = other_scale;
378 return true;
379 } else {
380 if (scale_ == 0) {
381 base_ = other_base;
382 offset_ += other_offset;
383 scale_ = other_scale;
384 return true;
385 } else {
386 return false;
387 }
388 }
389 }
390
391 void SwapValues(HValue** other_base, int* other_offset, int* other_scale) {
392 swap(&base_, other_base);
393 swap(&offset_, other_offset);
394 swap(&scale_, other_scale);
395 }
396
397 private:
398 template <class T> void swap(T* a, T* b) {
399 T c(*a);
400 *a = *b;
401 *b = c;
402 }
403
404 HValue* base_;
405 int offset_;
406 int scale_;
407 };
408
409
410 typedef EnumSet<GVNFlag, int32_t> GVNFlagSet;
411
412
413 class HValue : public ZoneObject {
414 public:
415 static const int kNoNumber = -1;
416
417 enum Flag {
418 kFlexibleRepresentation,
419 kCannotBeTagged,
420 // Participate in Global Value Numbering, i.e. elimination of
421 // unnecessary recomputations. If an instruction sets this flag, it must
422 // implement DataEquals(), which will be used to determine if other
423 // occurrences of the instruction are indeed the same.
424 kUseGVN,
425 // Track instructions that are dominating side effects. If an instruction
426 // sets this flag, it must implement HandleSideEffectDominator() and should
427 // indicate which side effects to track by setting GVN flags.
428 kTrackSideEffectDominators,
429 kCanOverflow,
430 kBailoutOnMinusZero,
431 kCanBeDivByZero,
432 kLeftCanBeMinInt,
433 kLeftCanBeNegative,
434 kLeftCanBePositive,
435 kAllowUndefinedAsNaN,
436 kIsArguments,
437 kTruncatingToInt32,
438 kAllUsesTruncatingToInt32,
439 kTruncatingToSmi,
440 kAllUsesTruncatingToSmi,
441 // Set after an instruction is killed.
442 kIsDead,
443 // Instructions that are allowed to produce full range unsigned integer
444 // values are marked with kUint32 flag. If arithmetic shift or a load from
445 // EXTERNAL_UINT32_ELEMENTS array is not marked with this flag
446 // it will deoptimize if result does not fit into signed integer range.
447 // HGraph::ComputeSafeUint32Operations is responsible for setting this
448 // flag.
449 kUint32,
450 kHasNoObservableSideEffects,
451 // Indicates an instruction shouldn't be replaced by optimization, this flag
452 // is useful to set in cases where recomputing a value is cheaper than
453 // extending the value's live range and spilling it.
454 kCantBeReplaced,
455 // Indicates the instruction is live during dead code elimination.
456 kIsLive,
457
458 // HEnvironmentMarkers are deleted before dead code
459 // elimination takes place, so they can repurpose the kIsLive flag:
460 kEndsLiveRange = kIsLive,
461
462 // TODO(everyone): Don't forget to update this!
463 kLastFlag = kIsLive
464 };
465
466 STATIC_ASSERT(kLastFlag < kBitsPerInt);
467
468 static HValue* cast(HValue* value) { return value; }
469
470 enum Opcode {
471 // Declare a unique enum value for each hydrogen instruction.
472 #define DECLARE_OPCODE(type) k##type,
473 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
474 kPhi
475 #undef DECLARE_OPCODE
476 };
477 virtual Opcode opcode() const = 0;
478
479 // Declare a non-virtual predicates for each concrete HInstruction or HValue.
480 #define DECLARE_PREDICATE(type) \
481 bool Is##type() const { return opcode() == k##type; }
482 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
483 #undef DECLARE_PREDICATE
484 bool IsPhi() const { return opcode() == kPhi; }
485
486 // Declare virtual predicates for abstract HInstruction or HValue
487 #define DECLARE_PREDICATE(type) \
488 virtual bool Is##type() const { return false; }
489 HYDROGEN_ABSTRACT_INSTRUCTION_LIST(DECLARE_PREDICATE)
490 #undef DECLARE_PREDICATE
491
492 bool IsBitwiseBinaryShift() {
493 return IsShl() || IsShr() || IsSar();
494 }
495
496 explicit HValue(HType type = HType::Tagged())
497 : block_(NULL),
498 id_(kNoNumber),
499 type_(type),
500 use_list_(NULL),
501 range_(NULL),
502 #ifdef DEBUG
503 range_poisoned_(false),
504 #endif
505 flags_(0) {}
506 virtual ~HValue() {}
507
508 virtual SourcePosition position() const { return SourcePosition::Unknown(); }
509 virtual SourcePosition operand_position(int index) const {
510 return position();
511 }
512
513 HBasicBlock* block() const { return block_; }
514 void SetBlock(HBasicBlock* block);
515
516 // Note: Never call this method for an unlinked value.
517 Isolate* isolate() const;
518
519 int id() const { return id_; }
520 void set_id(int id) { id_ = id; }
521
522 HUseIterator uses() const { return HUseIterator(use_list_); }
523
524 virtual bool EmitAtUses() { return false; }
525
526 Representation representation() const { return representation_; }
527 void ChangeRepresentation(Representation r) {
528 DCHECK(CheckFlag(kFlexibleRepresentation));
529 DCHECK(!CheckFlag(kCannotBeTagged) || !r.IsTagged());
530 RepresentationChanged(r);
531 representation_ = r;
532 if (r.IsTagged()) {
533 // Tagged is the bottom of the lattice, don't go any further.
534 ClearFlag(kFlexibleRepresentation);
535 }
536 }
537 virtual void AssumeRepresentation(Representation r);
538
539 virtual Representation KnownOptimalRepresentation() {
540 Representation r = representation();
541 if (r.IsTagged()) {
542 HType t = type();
543 if (t.IsSmi()) return Representation::Smi();
544 if (t.IsHeapNumber()) return Representation::Double();
545 if (t.IsHeapObject()) return r;
546 return Representation::None();
547 }
548 return r;
549 }
550
551 HType type() const { return type_; }
552 void set_type(HType new_type) {
553 DCHECK(new_type.IsSubtypeOf(type_));
554 type_ = new_type;
555 }
556
557 // There are HInstructions that do not really change a value, they
558 // only add pieces of information to it (like bounds checks, map checks,
559 // smi checks...).
560 // We call these instructions "informative definitions", or "iDef".
561 // One of the iDef operands is special because it is the value that is
562 // "transferred" to the output, we call it the "redefined operand".
563 // If an HValue is an iDef it must override RedefinedOperandIndex() so that
564 // it does not return kNoRedefinedOperand;
565 static const int kNoRedefinedOperand = -1;
566 virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; }
567 bool IsInformativeDefinition() {
568 return RedefinedOperandIndex() != kNoRedefinedOperand;
569 }
570 HValue* RedefinedOperand() {
571 int index = RedefinedOperandIndex();
572 return index == kNoRedefinedOperand ? NULL : OperandAt(index);
573 }
574
575 bool CanReplaceWithDummyUses();
576
577 virtual int argument_delta() const { return 0; }
578
579 // A purely informative definition is an idef that will not emit code and
580 // should therefore be removed from the graph in the RestoreActualValues
581 // phase (so that live ranges will be shorter).
582 virtual bool IsPurelyInformativeDefinition() { return false; }
583
584 // This method must always return the original HValue SSA definition,
585 // regardless of any chain of iDefs of this value.
586 HValue* ActualValue() {
587 HValue* value = this;
588 int index;
589 while ((index = value->RedefinedOperandIndex()) != kNoRedefinedOperand) {
590 value = value->OperandAt(index);
591 }
592 return value;
593 }
594
595 bool IsInteger32Constant();
596 int32_t GetInteger32Constant();
597 bool EqualsInteger32Constant(int32_t value);
598
599 bool IsDefinedAfter(HBasicBlock* other) const;
600
601 // Operands.
602 virtual int OperandCount() const = 0;
603 virtual HValue* OperandAt(int index) const = 0;
604 void SetOperandAt(int index, HValue* value);
605
606 void DeleteAndReplaceWith(HValue* other);
607 void ReplaceAllUsesWith(HValue* other);
608 bool HasNoUses() const { return use_list_ == NULL; }
609 bool HasOneUse() const {
610 return use_list_ != NULL && use_list_->tail() == NULL;
611 }
612 bool HasMultipleUses() const {
613 return use_list_ != NULL && use_list_->tail() != NULL;
614 }
615 int UseCount() const;
616
617 // Mark this HValue as dead and to be removed from other HValues' use lists.
618 void Kill();
619
620 int flags() const { return flags_; }
621 void SetFlag(Flag f) { flags_ |= (1 << f); }
622 void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
623 bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
624 void CopyFlag(Flag f, HValue* other) {
625 if (other->CheckFlag(f)) SetFlag(f);
626 }
627
628 // Returns true if the flag specified is set for all uses, false otherwise.
629 bool CheckUsesForFlag(Flag f) const;
630 // Same as before and the first one without the flag is returned in value.
631 bool CheckUsesForFlag(Flag f, HValue** value) const;
632 // Returns true if the flag specified is set for all uses, and this set
633 // of uses is non-empty.
634 bool HasAtLeastOneUseWithFlagAndNoneWithout(Flag f) const;
635
636 GVNFlagSet ChangesFlags() const { return changes_flags_; }
637 GVNFlagSet DependsOnFlags() const { return depends_on_flags_; }
638 void SetChangesFlag(GVNFlag f) { changes_flags_.Add(f); }
639 void SetDependsOnFlag(GVNFlag f) { depends_on_flags_.Add(f); }
640 void ClearChangesFlag(GVNFlag f) { changes_flags_.Remove(f); }
641 void ClearDependsOnFlag(GVNFlag f) { depends_on_flags_.Remove(f); }
642 bool CheckChangesFlag(GVNFlag f) const {
643 return changes_flags_.Contains(f);
644 }
645 bool CheckDependsOnFlag(GVNFlag f) const {
646 return depends_on_flags_.Contains(f);
647 }
648 void SetAllSideEffects() { changes_flags_.Add(AllSideEffectsFlagSet()); }
649 void ClearAllSideEffects() {
650 changes_flags_.Remove(AllSideEffectsFlagSet());
651 }
652 bool HasSideEffects() const {
653 return changes_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
654 }
655 bool HasObservableSideEffects() const {
656 return !CheckFlag(kHasNoObservableSideEffects) &&
657 changes_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
658 }
659
660 GVNFlagSet SideEffectFlags() const {
661 GVNFlagSet result = ChangesFlags();
662 result.Intersect(AllSideEffectsFlagSet());
663 return result;
664 }
665
666 GVNFlagSet ObservableChangesFlags() const {
667 GVNFlagSet result = ChangesFlags();
668 result.Intersect(AllObservableSideEffectsFlagSet());
669 return result;
670 }
671
672 Range* range() const {
673 DCHECK(!range_poisoned_);
674 return range_;
675 }
676 bool HasRange() const {
677 DCHECK(!range_poisoned_);
678 return range_ != NULL;
679 }
680 #ifdef DEBUG
681 void PoisonRange() { range_poisoned_ = true; }
682 #endif
683 void AddNewRange(Range* r, Zone* zone);
684 void RemoveLastAddedRange();
685 void ComputeInitialRange(Zone* zone);
686
687 // Escape analysis helpers.
688 virtual bool HasEscapingOperandAt(int index) { return true; }
689 virtual bool HasOutOfBoundsAccess(int size) { return false; }
690
691 // Representation helpers.
692 virtual Representation observed_input_representation(int index) {
693 return Representation::None();
694 }
695 virtual Representation RequiredInputRepresentation(int index) = 0;
696 virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
697
698 // This gives the instruction an opportunity to replace itself with an
699 // instruction that does the same in some better way. To replace an
700 // instruction with a new one, first add the new instruction to the graph,
701 // then return it. Return NULL to have the instruction deleted.
702 virtual HValue* Canonicalize() { return this; }
703
704 bool Equals(HValue* other);
705 virtual intptr_t Hashcode();
706
707 // Compute unique ids upfront that is safe wrt GC and concurrent compilation.
708 virtual void FinalizeUniqueness() { }
709
710 // Printing support.
711 virtual std::ostream& PrintTo(std::ostream& os) const = 0; // NOLINT
712
713 const char* Mnemonic() const;
714
715 // Type information helpers.
716 bool HasMonomorphicJSObjectType();
717
718 // TODO(mstarzinger): For now instructions can override this function to
719 // specify statically known types, once HType can convey more information
720 // it should be based on the HType.
721 virtual Handle<Map> GetMonomorphicJSObjectMap() { return Handle<Map>(); }
722
723 // Updated the inferred type of this instruction and returns true if
724 // it has changed.
725 bool UpdateInferredType();
726
727 virtual HType CalculateInferredType();
728
729 // This function must be overridden for instructions which have the
730 // kTrackSideEffectDominators flag set, to track instructions that are
731 // dominating side effects.
732 // It returns true if it removed an instruction which had side effects.
733 virtual bool HandleSideEffectDominator(GVNFlag side_effect,
734 HValue* dominator) {
735 UNREACHABLE();
736 return false;
737 }
738
739 // Check if this instruction has some reason that prevents elimination.
740 bool CannotBeEliminated() const {
741 return HasObservableSideEffects() || !IsDeletable();
742 }
743
744 #ifdef DEBUG
745 virtual void Verify() = 0;
746 #endif
747
748 virtual bool TryDecompose(DecompositionResult* decomposition) {
749 if (RedefinedOperand() != NULL) {
750 return RedefinedOperand()->TryDecompose(decomposition);
751 } else {
752 return false;
753 }
754 }
755
756 // Returns true conservatively if the program might be able to observe a
757 // ToString() operation on this value.
758 bool ToStringCanBeObserved() const {
759 return ToStringOrToNumberCanBeObserved();
760 }
761
762 // Returns true conservatively if the program might be able to observe a
763 // ToNumber() operation on this value.
764 bool ToNumberCanBeObserved() const {
765 return ToStringOrToNumberCanBeObserved();
766 }
767
768 MinusZeroMode GetMinusZeroMode() {
769 return CheckFlag(kBailoutOnMinusZero)
770 ? FAIL_ON_MINUS_ZERO : TREAT_MINUS_ZERO_AS_ZERO;
771 }
772
773 protected:
774 // This function must be overridden for instructions with flag kUseGVN, to
775 // compare the non-Operand parts of the instruction.
776 virtual bool DataEquals(HValue* other) {
777 UNREACHABLE();
778 return false;
779 }
780
781 bool ToStringOrToNumberCanBeObserved() const {
782 if (type().IsTaggedPrimitive()) return false;
783 if (type().IsJSObject()) return true;
784 return !representation().IsSmiOrInteger32() && !representation().IsDouble();
785 }
786
787 virtual Representation RepresentationFromInputs() {
788 return representation();
789 }
790 virtual Representation RepresentationFromUses();
791 Representation RepresentationFromUseRequirements();
792 bool HasNonSmiUse();
793 virtual void UpdateRepresentation(Representation new_rep,
794 HInferRepresentationPhase* h_infer,
795 const char* reason);
796 void AddDependantsToWorklist(HInferRepresentationPhase* h_infer);
797
798 virtual void RepresentationChanged(Representation to) { }
799
800 virtual Range* InferRange(Zone* zone);
801 virtual void DeleteFromGraph() = 0;
802 virtual void InternalSetOperandAt(int index, HValue* value) = 0;
803 void clear_block() {
804 DCHECK(block_ != NULL);
805 block_ = NULL;
806 }
807
808 void set_representation(Representation r) {
809 DCHECK(representation_.IsNone() && !r.IsNone());
810 representation_ = r;
811 }
812
813 static GVNFlagSet AllFlagSet() {
814 GVNFlagSet result;
815 #define ADD_FLAG(Type) result.Add(k##Type);
816 GVN_TRACKED_FLAG_LIST(ADD_FLAG)
817 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG)
818 #undef ADD_FLAG
819 return result;
820 }
821
822 // A flag mask to mark an instruction as having arbitrary side effects.
823 static GVNFlagSet AllSideEffectsFlagSet() {
824 GVNFlagSet result = AllFlagSet();
825 result.Remove(kOsrEntries);
826 return result;
827 }
828 friend std::ostream& operator<<(std::ostream& os, const ChangesOf& v);
829
830 // A flag mask of all side effects that can make observable changes in
831 // an executing program (i.e. are not safe to repeat, move or remove);
832 static GVNFlagSet AllObservableSideEffectsFlagSet() {
833 GVNFlagSet result = AllFlagSet();
834 result.Remove(kNewSpacePromotion);
835 result.Remove(kElementsKind);
836 result.Remove(kElementsPointer);
837 result.Remove(kMaps);
838 return result;
839 }
840
841 // Remove the matching use from the use list if present. Returns the
842 // removed list node or NULL.
843 HUseListNode* RemoveUse(HValue* value, int index);
844
845 void RegisterUse(int index, HValue* new_value);
846
847 HBasicBlock* block_;
848
849 // The id of this instruction in the hydrogen graph, assigned when first
850 // added to the graph. Reflects creation order.
851 int id_;
852
853 Representation representation_;
854 HType type_;
855 HUseListNode* use_list_;
856 Range* range_;
857 #ifdef DEBUG
858 bool range_poisoned_;
859 #endif
860 int flags_;
861 GVNFlagSet changes_flags_;
862 GVNFlagSet depends_on_flags_;
863
864 private:
865 virtual bool IsDeletable() const { return false; }
866
867 DISALLOW_COPY_AND_ASSIGN(HValue);
868 };
869
870 // Support for printing various aspects of an HValue.
871 struct NameOf {
872 explicit NameOf(const HValue* const v) : value(v) {}
873 const HValue* value;
874 };
875
876
877 struct TypeOf {
878 explicit TypeOf(const HValue* const v) : value(v) {}
879 const HValue* value;
880 };
881
882
883 struct ChangesOf {
884 explicit ChangesOf(const HValue* const v) : value(v) {}
885 const HValue* value;
886 };
887
888
889 std::ostream& operator<<(std::ostream& os, const HValue& v);
890 std::ostream& operator<<(std::ostream& os, const NameOf& v);
891 std::ostream& operator<<(std::ostream& os, const TypeOf& v);
892 std::ostream& operator<<(std::ostream& os, const ChangesOf& v);
893
894
895 #define DECLARE_INSTRUCTION_FACTORY_P0(I) \
896 static I* New(Isolate* isolate, Zone* zone, HValue* context) { \
897 return new (zone) I(); \
898 }
899
900 #define DECLARE_INSTRUCTION_FACTORY_P1(I, P1) \
901 static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1) { \
902 return new (zone) I(p1); \
903 }
904
905 #define DECLARE_INSTRUCTION_FACTORY_P2(I, P1, P2) \
906 static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2) { \
907 return new (zone) I(p1, p2); \
908 }
909
910 #define DECLARE_INSTRUCTION_FACTORY_P3(I, P1, P2, P3) \
911 static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
912 P3 p3) { \
913 return new (zone) I(p1, p2, p3); \
914 }
915
916 #define DECLARE_INSTRUCTION_FACTORY_P4(I, P1, P2, P3, P4) \
917 static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
918 P3 p3, P4 p4) { \
919 return new (zone) I(p1, p2, p3, p4); \
920 }
921
922 #define DECLARE_INSTRUCTION_FACTORY_P5(I, P1, P2, P3, P4, P5) \
923 static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
924 P3 p3, P4 p4, P5 p5) { \
925 return new (zone) I(p1, p2, p3, p4, p5); \
926 }
927
928 #define DECLARE_INSTRUCTION_FACTORY_P6(I, P1, P2, P3, P4, P5, P6) \
929 static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
930 P3 p3, P4 p4, P5 p5, P6 p6) { \
931 return new (zone) I(p1, p2, p3, p4, p5, p6); \
932 }
933
934 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P0(I) \
935 static I* New(Isolate* isolate, Zone* zone, HValue* context) { \
936 return new (zone) I(context); \
937 }
938
939 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(I, P1) \
940 static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1) { \
941 return new (zone) I(context, p1); \
942 }
943
944 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(I, P1, P2) \
945 static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2) { \
946 return new (zone) I(context, p1, p2); \
947 }
948
949 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(I, P1, P2, P3) \
950 static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
951 P3 p3) { \
952 return new (zone) I(context, p1, p2, p3); \
953 }
954
955 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(I, P1, P2, P3, P4) \
956 static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
957 P3 p3, P4 p4) { \
958 return new (zone) I(context, p1, p2, p3, p4); \
959 }
960
961 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(I, P1, P2, P3, P4, P5) \
962 static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
963 P3 p3, P4 p4, P5 p5) { \
964 return new (zone) I(context, p1, p2, p3, p4, p5); \
965 }
966
967 #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P6(I, P1, P2, P3, P4, P5, P6) \
968 static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
969 P3 p3, P4 p4, P5 p5, P6 p6) { \
970 return new (zone) I(context, p1, p2, p3, p4, p5, p6); \
971 }
972
973
974 // A helper class to represent per-operand position information attached to
975 // the HInstruction in the compact form. Uses tagging to distinguish between
976 // case when only instruction's position is available and case when operands'
977 // positions are also available.
978 // In the first case it contains intruction's position as a tagged value.
979 // In the second case it points to an array which contains instruction's
980 // position and operands' positions.
981 class HPositionInfo {
982 public:
983 explicit HPositionInfo(int pos) : data_(TagPosition(pos)) { }
984
985 SourcePosition position() const {
986 if (has_operand_positions()) {
987 return operand_positions()[kInstructionPosIndex];
988 }
989 return SourcePosition::FromRaw(static_cast<int>(UntagPosition(data_)));
990 }
991
992 void set_position(SourcePosition pos) {
993 if (has_operand_positions()) {
994 operand_positions()[kInstructionPosIndex] = pos;
995 } else {
996 data_ = TagPosition(pos.raw());
997 }
998 }
999
1000 void ensure_storage_for_operand_positions(Zone* zone, int operand_count) {
1001 if (has_operand_positions()) {
1002 return;
1003 }
1004
1005 const int length = kFirstOperandPosIndex + operand_count;
1006 SourcePosition* positions = zone->NewArray<SourcePosition>(length);
1007 for (int i = 0; i < length; i++) {
1008 positions[i] = SourcePosition::Unknown();
1009 }
1010
1011 const SourcePosition pos = position();
1012 data_ = reinterpret_cast<intptr_t>(positions);
1013 set_position(pos);
1014
1015 DCHECK(has_operand_positions());
1016 }
1017
1018 SourcePosition operand_position(int idx) const {
1019 if (!has_operand_positions()) {
1020 return position();
1021 }
1022 return *operand_position_slot(idx);
1023 }
1024
1025 void set_operand_position(int idx, SourcePosition pos) {
1026 *operand_position_slot(idx) = pos;
1027 }
1028
1029 private:
1030 static const intptr_t kInstructionPosIndex = 0;
1031 static const intptr_t kFirstOperandPosIndex = 1;
1032
1033 SourcePosition* operand_position_slot(int idx) const {
1034 DCHECK(has_operand_positions());
1035 return &(operand_positions()[kFirstOperandPosIndex + idx]);
1036 }
1037
1038 bool has_operand_positions() const {
1039 return !IsTaggedPosition(data_);
1040 }
1041
1042 SourcePosition* operand_positions() const {
1043 DCHECK(has_operand_positions());
1044 return reinterpret_cast<SourcePosition*>(data_);
1045 }
1046
1047 static const intptr_t kPositionTag = 1;
1048 static const intptr_t kPositionShift = 1;
1049 static bool IsTaggedPosition(intptr_t val) {
1050 return (val & kPositionTag) != 0;
1051 }
1052 static intptr_t UntagPosition(intptr_t val) {
1053 DCHECK(IsTaggedPosition(val));
1054 return val >> kPositionShift;
1055 }
1056 static intptr_t TagPosition(intptr_t val) {
1057 const intptr_t result = (val << kPositionShift) | kPositionTag;
1058 DCHECK(UntagPosition(result) == val);
1059 return result;
1060 }
1061
1062 intptr_t data_;
1063 };
1064
1065
1066 class HInstruction : public HValue {
1067 public:
1068 HInstruction* next() const { return next_; }
1069 HInstruction* previous() const { return previous_; }
1070
1071 std::ostream& PrintTo(std::ostream& os) const override; // NOLINT
1072 virtual std::ostream& PrintDataTo(std::ostream& os) const; // NOLINT
1073
1074 bool IsLinked() const { return block() != NULL; }
1075 void Unlink();
1076
1077 void InsertBefore(HInstruction* next);
1078
1079 template<class T> T* Prepend(T* instr) {
1080 instr->InsertBefore(this);
1081 return instr;
1082 }
1083
1084 void InsertAfter(HInstruction* previous);
1085
1086 template<class T> T* Append(T* instr) {
1087 instr->InsertAfter(this);
1088 return instr;
1089 }
1090
1091 // The position is a write-once variable.
1092 SourcePosition position() const override {
1093 return SourcePosition(position_.position());
1094 }
1095 bool has_position() const {
1096 return !position().IsUnknown();
1097 }
1098 void set_position(SourcePosition position) {
1099 DCHECK(!has_position());
1100 DCHECK(!position.IsUnknown());
1101 position_.set_position(position);
1102 }
1103
1104 SourcePosition operand_position(int index) const override {
1105 const SourcePosition pos = position_.operand_position(index);
1106 return pos.IsUnknown() ? position() : pos;
1107 }
1108 void set_operand_position(Zone* zone, int index, SourcePosition pos) {
1109 DCHECK(0 <= index && index < OperandCount());
1110 position_.ensure_storage_for_operand_positions(zone, OperandCount());
1111 position_.set_operand_position(index, pos);
1112 }
1113
1114 bool Dominates(HInstruction* other);
1115 bool CanTruncateToSmi() const { return CheckFlag(kTruncatingToSmi); }
1116 bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); }
1117
1118 virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
1119
1120 #ifdef DEBUG
1121 void Verify() override;
1122 #endif
1123
1124 bool CanDeoptimize();
1125
1126 virtual bool HasStackCheck() { return false; }
1127
1128 DECLARE_ABSTRACT_INSTRUCTION(Instruction)
1129
1130 protected:
1131 explicit HInstruction(HType type = HType::Tagged())
1132 : HValue(type),
1133 next_(NULL),
1134 previous_(NULL),
1135 position_(RelocInfo::kNoPosition) {
1136 SetDependsOnFlag(kOsrEntries);
1137 }
1138
1139 void DeleteFromGraph() override { Unlink(); }
1140
1141 private:
1142 void InitializeAsFirst(HBasicBlock* block) {
1143 DCHECK(!IsLinked());
1144 SetBlock(block);
1145 }
1146
1147 HInstruction* next_;
1148 HInstruction* previous_;
1149 HPositionInfo position_;
1150
1151 friend class HBasicBlock;
1152 };
1153
1154
1155 template<int V>
1156 class HTemplateInstruction : public HInstruction {
1157 public:
1158 int OperandCount() const final { return V; }
1159 HValue* OperandAt(int i) const final { return inputs_[i]; }
1160
1161 protected:
1162 explicit HTemplateInstruction(HType type = HType::Tagged())
1163 : HInstruction(type) {}
1164
1165 void InternalSetOperandAt(int i, HValue* value) final { inputs_[i] = value; }
1166
1167 private:
1168 EmbeddedContainer<HValue*, V> inputs_;
1169 };
1170
1171
1172 class HControlInstruction : public HInstruction {
1173 public:
1174 virtual HBasicBlock* SuccessorAt(int i) const = 0;
1175 virtual int SuccessorCount() const = 0;
1176 virtual void SetSuccessorAt(int i, HBasicBlock* block) = 0;
1177
1178 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1179
1180 virtual bool KnownSuccessorBlock(HBasicBlock** block) {
1181 *block = NULL;
1182 return false;
1183 }
1184
1185 HBasicBlock* FirstSuccessor() {
1186 return SuccessorCount() > 0 ? SuccessorAt(0) : NULL;
1187 }
1188 HBasicBlock* SecondSuccessor() {
1189 return SuccessorCount() > 1 ? SuccessorAt(1) : NULL;
1190 }
1191
1192 void Not() {
1193 HBasicBlock* swap = SuccessorAt(0);
1194 SetSuccessorAt(0, SuccessorAt(1));
1195 SetSuccessorAt(1, swap);
1196 }
1197
1198 DECLARE_ABSTRACT_INSTRUCTION(ControlInstruction)
1199 };
1200
1201
1202 class HSuccessorIterator final BASE_EMBEDDED {
1203 public:
1204 explicit HSuccessorIterator(const HControlInstruction* instr)
1205 : instr_(instr), current_(0) {}
1206
1207 bool Done() { return current_ >= instr_->SuccessorCount(); }
1208 HBasicBlock* Current() { return instr_->SuccessorAt(current_); }
1209 void Advance() { current_++; }
1210
1211 private:
1212 const HControlInstruction* instr_;
1213 int current_;
1214 };
1215
1216
1217 template<int S, int V>
1218 class HTemplateControlInstruction : public HControlInstruction {
1219 public:
1220 int SuccessorCount() const override { return S; }
1221 HBasicBlock* SuccessorAt(int i) const override { return successors_[i]; }
1222 void SetSuccessorAt(int i, HBasicBlock* block) override {
1223 successors_[i] = block;
1224 }
1225
1226 int OperandCount() const override { return V; }
1227 HValue* OperandAt(int i) const override { return inputs_[i]; }
1228
1229
1230 protected:
1231 void InternalSetOperandAt(int i, HValue* value) override {
1232 inputs_[i] = value;
1233 }
1234
1235 private:
1236 EmbeddedContainer<HBasicBlock*, S> successors_;
1237 EmbeddedContainer<HValue*, V> inputs_;
1238 };
1239
1240
1241 class HBlockEntry final : public HTemplateInstruction<0> {
1242 public:
1243 Representation RequiredInputRepresentation(int index) override {
1244 return Representation::None();
1245 }
1246
1247 DECLARE_CONCRETE_INSTRUCTION(BlockEntry)
1248 };
1249
1250
1251 class HDummyUse final : public HTemplateInstruction<1> {
1252 public:
1253 explicit HDummyUse(HValue* value)
1254 : HTemplateInstruction<1>(HType::Smi()) {
1255 SetOperandAt(0, value);
1256 // Pretend to be a Smi so that the HChange instructions inserted
1257 // before any use generate as little code as possible.
1258 set_representation(Representation::Tagged());
1259 }
1260
1261 HValue* value() const { return OperandAt(0); }
1262
1263 bool HasEscapingOperandAt(int index) override { return false; }
1264 Representation RequiredInputRepresentation(int index) override {
1265 return Representation::None();
1266 }
1267
1268 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1269
1270 DECLARE_CONCRETE_INSTRUCTION(DummyUse);
1271 };
1272
1273
1274 // Inserts an int3/stop break instruction for debugging purposes.
1275 class HDebugBreak final : public HTemplateInstruction<0> {
1276 public:
1277 DECLARE_INSTRUCTION_FACTORY_P0(HDebugBreak);
1278
1279 Representation RequiredInputRepresentation(int index) override {
1280 return Representation::None();
1281 }
1282
1283 DECLARE_CONCRETE_INSTRUCTION(DebugBreak)
1284 };
1285
1286
1287 class HPrologue final : public HTemplateInstruction<0> {
1288 public:
1289 static HPrologue* New(Zone* zone) { return new (zone) HPrologue(); }
1290
1291 Representation RequiredInputRepresentation(int index) override {
1292 return Representation::None();
1293 }
1294
1295 DECLARE_CONCRETE_INSTRUCTION(Prologue)
1296 };
1297
1298
1299 class HGoto final : public HTemplateControlInstruction<1, 0> {
1300 public:
1301 explicit HGoto(HBasicBlock* target) {
1302 SetSuccessorAt(0, target);
1303 }
1304
1305 bool KnownSuccessorBlock(HBasicBlock** block) override {
1306 *block = FirstSuccessor();
1307 return true;
1308 }
1309
1310 Representation RequiredInputRepresentation(int index) override {
1311 return Representation::None();
1312 }
1313
1314 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1315
1316 DECLARE_CONCRETE_INSTRUCTION(Goto)
1317 };
1318
1319
1320 class HDeoptimize final : public HTemplateControlInstruction<1, 0> {
1321 public:
1322 static HDeoptimize* New(Isolate* isolate, Zone* zone, HValue* context,
1323 Deoptimizer::DeoptReason reason,
1324 Deoptimizer::BailoutType type,
1325 HBasicBlock* unreachable_continuation) {
1326 return new(zone) HDeoptimize(reason, type, unreachable_continuation);
1327 }
1328
1329 bool KnownSuccessorBlock(HBasicBlock** block) override {
1330 *block = NULL;
1331 return true;
1332 }
1333
1334 Representation RequiredInputRepresentation(int index) override {
1335 return Representation::None();
1336 }
1337
1338 Deoptimizer::DeoptReason reason() const { return reason_; }
1339 Deoptimizer::BailoutType type() { return type_; }
1340
1341 DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
1342
1343 private:
1344 explicit HDeoptimize(Deoptimizer::DeoptReason reason,
1345 Deoptimizer::BailoutType type,
1346 HBasicBlock* unreachable_continuation)
1347 : reason_(reason), type_(type) {
1348 SetSuccessorAt(0, unreachable_continuation);
1349 }
1350
1351 Deoptimizer::DeoptReason reason_;
1352 Deoptimizer::BailoutType type_;
1353 };
1354
1355
1356 class HUnaryControlInstruction : public HTemplateControlInstruction<2, 1> {
1357 public:
1358 HUnaryControlInstruction(HValue* value,
1359 HBasicBlock* true_target,
1360 HBasicBlock* false_target) {
1361 SetOperandAt(0, value);
1362 SetSuccessorAt(0, true_target);
1363 SetSuccessorAt(1, false_target);
1364 }
1365
1366 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1367
1368 HValue* value() const { return OperandAt(0); }
1369 };
1370
1371
1372 class HBranch final : public HUnaryControlInstruction {
1373 public:
1374 DECLARE_INSTRUCTION_FACTORY_P1(HBranch, HValue*);
1375 DECLARE_INSTRUCTION_FACTORY_P2(HBranch, HValue*,
1376 ToBooleanStub::Types);
1377 DECLARE_INSTRUCTION_FACTORY_P4(HBranch, HValue*,
1378 ToBooleanStub::Types,
1379 HBasicBlock*, HBasicBlock*);
1380
1381 Representation RequiredInputRepresentation(int index) override {
1382 return Representation::None();
1383 }
1384 Representation observed_input_representation(int index) override;
1385
1386 bool KnownSuccessorBlock(HBasicBlock** block) override;
1387
1388 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1389
1390 ToBooleanStub::Types expected_input_types() const {
1391 return expected_input_types_;
1392 }
1393
1394 DECLARE_CONCRETE_INSTRUCTION(Branch)
1395
1396 private:
1397 HBranch(HValue* value,
1398 ToBooleanStub::Types expected_input_types = ToBooleanStub::Types(),
1399 HBasicBlock* true_target = NULL,
1400 HBasicBlock* false_target = NULL)
1401 : HUnaryControlInstruction(value, true_target, false_target),
1402 expected_input_types_(expected_input_types) {
1403 SetFlag(kAllowUndefinedAsNaN);
1404 }
1405
1406 ToBooleanStub::Types expected_input_types_;
1407 };
1408
1409
1410 class HCompareMap final : public HUnaryControlInstruction {
1411 public:
1412 DECLARE_INSTRUCTION_FACTORY_P2(HCompareMap, HValue*, Handle<Map>);
1413 DECLARE_INSTRUCTION_FACTORY_P4(HCompareMap, HValue*, Handle<Map>,
1414 HBasicBlock*, HBasicBlock*);
1415
1416 bool KnownSuccessorBlock(HBasicBlock** block) override {
1417 if (known_successor_index() != kNoKnownSuccessorIndex) {
1418 *block = SuccessorAt(known_successor_index());
1419 return true;
1420 }
1421 *block = NULL;
1422 return false;
1423 }
1424
1425 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1426
1427 static const int kNoKnownSuccessorIndex = -1;
1428 int known_successor_index() const {
1429 return KnownSuccessorIndexField::decode(bit_field_) -
1430 kInternalKnownSuccessorOffset;
1431 }
1432 void set_known_successor_index(int index) {
1433 DCHECK(index >= 0 - kInternalKnownSuccessorOffset);
1434 bit_field_ = KnownSuccessorIndexField::update(
1435 bit_field_, index + kInternalKnownSuccessorOffset);
1436 }
1437
1438 Unique<Map> map() const { return map_; }
1439 bool map_is_stable() const { return MapIsStableField::decode(bit_field_); }
1440
1441 Representation RequiredInputRepresentation(int index) override {
1442 return Representation::Tagged();
1443 }
1444
1445 DECLARE_CONCRETE_INSTRUCTION(CompareMap)
1446
1447 protected:
1448 int RedefinedOperandIndex() override { return 0; }
1449
1450 private:
1451 HCompareMap(HValue* value, Handle<Map> map, HBasicBlock* true_target = NULL,
1452 HBasicBlock* false_target = NULL)
1453 : HUnaryControlInstruction(value, true_target, false_target),
1454 bit_field_(KnownSuccessorIndexField::encode(
1455 kNoKnownSuccessorIndex + kInternalKnownSuccessorOffset) |
1456 MapIsStableField::encode(map->is_stable())),
1457 map_(Unique<Map>::CreateImmovable(map)) {
1458 set_representation(Representation::Tagged());
1459 }
1460
1461 // BitFields can only store unsigned values, so use an offset.
1462 // Adding kInternalKnownSuccessorOffset must yield an unsigned value.
1463 static const int kInternalKnownSuccessorOffset = 1;
1464 STATIC_ASSERT(kNoKnownSuccessorIndex + kInternalKnownSuccessorOffset >= 0);
1465
1466 class KnownSuccessorIndexField : public BitField<int, 0, 31> {};
1467 class MapIsStableField : public BitField<bool, 31, 1> {};
1468
1469 uint32_t bit_field_;
1470 Unique<Map> map_;
1471 };
1472
1473
1474 class HContext final : public HTemplateInstruction<0> {
1475 public:
1476 static HContext* New(Zone* zone) {
1477 return new(zone) HContext();
1478 }
1479
1480 Representation RequiredInputRepresentation(int index) override {
1481 return Representation::None();
1482 }
1483
1484 DECLARE_CONCRETE_INSTRUCTION(Context)
1485
1486 protected:
1487 bool DataEquals(HValue* other) override { return true; }
1488
1489 private:
1490 HContext() {
1491 set_representation(Representation::Tagged());
1492 SetFlag(kUseGVN);
1493 }
1494
1495 bool IsDeletable() const override { return true; }
1496 };
1497
1498
1499 class HReturn final : public HTemplateControlInstruction<0, 3> {
1500 public:
1501 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HReturn, HValue*, HValue*);
1502 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HReturn, HValue*);
1503
1504 Representation RequiredInputRepresentation(int index) override {
1505 // TODO(titzer): require an Int32 input for faster returns.
1506 if (index == 2) return Representation::Smi();
1507 return Representation::Tagged();
1508 }
1509
1510 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1511
1512 HValue* value() const { return OperandAt(0); }
1513 HValue* context() const { return OperandAt(1); }
1514 HValue* parameter_count() const { return OperandAt(2); }
1515
1516 DECLARE_CONCRETE_INSTRUCTION(Return)
1517
1518 private:
1519 HReturn(HValue* context, HValue* value, HValue* parameter_count = 0) {
1520 SetOperandAt(0, value);
1521 SetOperandAt(1, context);
1522 SetOperandAt(2, parameter_count);
1523 }
1524 };
1525
1526
1527 class HAbnormalExit final : public HTemplateControlInstruction<0, 0> {
1528 public:
1529 DECLARE_INSTRUCTION_FACTORY_P0(HAbnormalExit);
1530
1531 Representation RequiredInputRepresentation(int index) override {
1532 return Representation::None();
1533 }
1534
1535 DECLARE_CONCRETE_INSTRUCTION(AbnormalExit)
1536 private:
1537 HAbnormalExit() {}
1538 };
1539
1540
1541 class HUnaryOperation : public HTemplateInstruction<1> {
1542 public:
1543 explicit HUnaryOperation(HValue* value, HType type = HType::Tagged())
1544 : HTemplateInstruction<1>(type) {
1545 SetOperandAt(0, value);
1546 }
1547
1548 static HUnaryOperation* cast(HValue* value) {
1549 return reinterpret_cast<HUnaryOperation*>(value);
1550 }
1551
1552 HValue* value() const { return OperandAt(0); }
1553 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1554 };
1555
1556
1557 class HUseConst final : public HUnaryOperation {
1558 public:
1559 DECLARE_INSTRUCTION_FACTORY_P1(HUseConst, HValue*);
1560
1561 Representation RequiredInputRepresentation(int index) override {
1562 return Representation::None();
1563 }
1564
1565 DECLARE_CONCRETE_INSTRUCTION(UseConst)
1566
1567 private:
1568 explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
1569 };
1570
1571
1572 class HForceRepresentation final : public HTemplateInstruction<1> {
1573 public:
1574 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
1575 HValue* value,
1576 Representation required_representation);
1577
1578 HValue* value() const { return OperandAt(0); }
1579
1580 Representation observed_input_representation(int index) override {
1581 // We haven't actually *observed* this, but it's closer to the truth
1582 // than 'None'.
1583 return representation(); // Same as the output representation.
1584 }
1585 Representation RequiredInputRepresentation(int index) override {
1586 return representation(); // Same as the output representation.
1587 }
1588
1589 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1590
1591 DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation)
1592
1593 private:
1594 HForceRepresentation(HValue* value, Representation required_representation) {
1595 SetOperandAt(0, value);
1596 set_representation(required_representation);
1597 }
1598 };
1599
1600
1601 class HChange final : public HUnaryOperation {
1602 public:
1603 HChange(HValue* value,
1604 Representation to,
1605 bool is_truncating_to_smi,
1606 bool is_truncating_to_int32)
1607 : HUnaryOperation(value) {
1608 DCHECK(!value->representation().IsNone());
1609 DCHECK(!to.IsNone());
1610 DCHECK(!value->representation().Equals(to));
1611 set_representation(to);
1612 SetFlag(kUseGVN);
1613 SetFlag(kCanOverflow);
1614 if (is_truncating_to_smi && to.IsSmi()) {
1615 SetFlag(kTruncatingToSmi);
1616 SetFlag(kTruncatingToInt32);
1617 }
1618 if (is_truncating_to_int32) SetFlag(kTruncatingToInt32);
1619 if (value->representation().IsSmi() || value->type().IsSmi()) {
1620 set_type(HType::Smi());
1621 } else {
1622 set_type(HType::TaggedNumber());
1623 if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
1624 }
1625 }
1626
1627 bool can_convert_undefined_to_nan() {
1628 return CheckUsesForFlag(kAllowUndefinedAsNaN);
1629 }
1630
1631 HType CalculateInferredType() override;
1632 HValue* Canonicalize() override;
1633
1634 Representation from() const { return value()->representation(); }
1635 Representation to() const { return representation(); }
1636 bool deoptimize_on_minus_zero() const {
1637 return CheckFlag(kBailoutOnMinusZero);
1638 }
1639 Representation RequiredInputRepresentation(int index) override {
1640 return from();
1641 }
1642
1643 Range* InferRange(Zone* zone) override;
1644
1645 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1646
1647 DECLARE_CONCRETE_INSTRUCTION(Change)
1648
1649 protected:
1650 bool DataEquals(HValue* other) override { return true; }
1651
1652 private:
1653 bool IsDeletable() const override {
1654 return !from().IsTagged() || value()->type().IsSmi();
1655 }
1656 };
1657
1658
1659 class HClampToUint8 final : public HUnaryOperation {
1660 public:
1661 DECLARE_INSTRUCTION_FACTORY_P1(HClampToUint8, HValue*);
1662
1663 Representation RequiredInputRepresentation(int index) override {
1664 return Representation::None();
1665 }
1666
1667 DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
1668
1669 protected:
1670 bool DataEquals(HValue* other) override { return true; }
1671
1672 private:
1673 explicit HClampToUint8(HValue* value)
1674 : HUnaryOperation(value) {
1675 set_representation(Representation::Integer32());
1676 SetFlag(kAllowUndefinedAsNaN);
1677 SetFlag(kUseGVN);
1678 }
1679
1680 bool IsDeletable() const override { return true; }
1681 };
1682
1683
1684 class HDoubleBits final : public HUnaryOperation {
1685 public:
1686 enum Bits { HIGH, LOW };
1687 DECLARE_INSTRUCTION_FACTORY_P2(HDoubleBits, HValue*, Bits);
1688
1689 Representation RequiredInputRepresentation(int index) override {
1690 return Representation::Double();
1691 }
1692
1693 DECLARE_CONCRETE_INSTRUCTION(DoubleBits)
1694
1695 Bits bits() { return bits_; }
1696
1697 protected:
1698 bool DataEquals(HValue* other) override {
1699 return other->IsDoubleBits() && HDoubleBits::cast(other)->bits() == bits();
1700 }
1701
1702 private:
1703 HDoubleBits(HValue* value, Bits bits)
1704 : HUnaryOperation(value), bits_(bits) {
1705 set_representation(Representation::Integer32());
1706 SetFlag(kUseGVN);
1707 }
1708
1709 bool IsDeletable() const override { return true; }
1710
1711 Bits bits_;
1712 };
1713
1714
1715 class HConstructDouble final : public HTemplateInstruction<2> {
1716 public:
1717 DECLARE_INSTRUCTION_FACTORY_P2(HConstructDouble, HValue*, HValue*);
1718
1719 Representation RequiredInputRepresentation(int index) override {
1720 return Representation::Integer32();
1721 }
1722
1723 DECLARE_CONCRETE_INSTRUCTION(ConstructDouble)
1724
1725 HValue* hi() { return OperandAt(0); }
1726 HValue* lo() { return OperandAt(1); }
1727
1728 protected:
1729 bool DataEquals(HValue* other) override { return true; }
1730
1731 private:
1732 explicit HConstructDouble(HValue* hi, HValue* lo) {
1733 set_representation(Representation::Double());
1734 SetFlag(kUseGVN);
1735 SetOperandAt(0, hi);
1736 SetOperandAt(1, lo);
1737 }
1738
1739 bool IsDeletable() const override { return true; }
1740 };
1741
1742
1743 enum RemovableSimulate {
1744 REMOVABLE_SIMULATE,
1745 FIXED_SIMULATE
1746 };
1747
1748
1749 class HSimulate final : public HInstruction {
1750 public:
1751 HSimulate(BailoutId ast_id, int pop_count, Zone* zone,
1752 RemovableSimulate removable)
1753 : ast_id_(ast_id),
1754 pop_count_(pop_count),
1755 values_(2, zone),
1756 assigned_indexes_(2, zone),
1757 zone_(zone),
1758 bit_field_(RemovableField::encode(removable) |
1759 DoneWithReplayField::encode(false)) {}
1760 ~HSimulate() {}
1761
1762 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1763
1764 bool HasAstId() const { return !ast_id_.IsNone(); }
1765 BailoutId ast_id() const { return ast_id_; }
1766 void set_ast_id(BailoutId id) {
1767 DCHECK(!HasAstId());
1768 ast_id_ = id;
1769 }
1770
1771 int pop_count() const { return pop_count_; }
1772 const ZoneList<HValue*>* values() const { return &values_; }
1773 int GetAssignedIndexAt(int index) const {
1774 DCHECK(HasAssignedIndexAt(index));
1775 return assigned_indexes_[index];
1776 }
1777 bool HasAssignedIndexAt(int index) const {
1778 return assigned_indexes_[index] != kNoIndex;
1779 }
1780 void AddAssignedValue(int index, HValue* value) {
1781 AddValue(index, value);
1782 }
1783 void AddPushedValue(HValue* value) {
1784 AddValue(kNoIndex, value);
1785 }
1786 int ToOperandIndex(int environment_index) {
1787 for (int i = 0; i < assigned_indexes_.length(); ++i) {
1788 if (assigned_indexes_[i] == environment_index) return i;
1789 }
1790 return -1;
1791 }
1792 int OperandCount() const override { return values_.length(); }
1793 HValue* OperandAt(int index) const override { return values_[index]; }
1794
1795 bool HasEscapingOperandAt(int index) override { return false; }
1796 Representation RequiredInputRepresentation(int index) override {
1797 return Representation::None();
1798 }
1799
1800 void MergeWith(ZoneList<HSimulate*>* list);
1801 bool is_candidate_for_removal() {
1802 return RemovableField::decode(bit_field_) == REMOVABLE_SIMULATE;
1803 }
1804
1805 // Replay effects of this instruction on the given environment.
1806 void ReplayEnvironment(HEnvironment* env);
1807
1808 DECLARE_CONCRETE_INSTRUCTION(Simulate)
1809
1810 #ifdef DEBUG
1811 void Verify() override;
1812 void set_closure(Handle<JSFunction> closure) { closure_ = closure; }
1813 Handle<JSFunction> closure() const { return closure_; }
1814 #endif
1815
1816 protected:
1817 void InternalSetOperandAt(int index, HValue* value) override {
1818 values_[index] = value;
1819 }
1820
1821 private:
1822 static const int kNoIndex = -1;
1823 void AddValue(int index, HValue* value) {
1824 assigned_indexes_.Add(index, zone_);
1825 // Resize the list of pushed values.
1826 values_.Add(NULL, zone_);
1827 // Set the operand through the base method in HValue to make sure that the
1828 // use lists are correctly updated.
1829 SetOperandAt(values_.length() - 1, value);
1830 }
1831 bool HasValueForIndex(int index) {
1832 for (int i = 0; i < assigned_indexes_.length(); ++i) {
1833 if (assigned_indexes_[i] == index) return true;
1834 }
1835 return false;
1836 }
1837 bool is_done_with_replay() const {
1838 return DoneWithReplayField::decode(bit_field_);
1839 }
1840 void set_done_with_replay() {
1841 bit_field_ = DoneWithReplayField::update(bit_field_, true);
1842 }
1843
1844 class RemovableField : public BitField<RemovableSimulate, 0, 1> {};
1845 class DoneWithReplayField : public BitField<bool, 1, 1> {};
1846
1847 BailoutId ast_id_;
1848 int pop_count_;
1849 ZoneList<HValue*> values_;
1850 ZoneList<int> assigned_indexes_;
1851 Zone* zone_;
1852 uint32_t bit_field_;
1853
1854 #ifdef DEBUG
1855 Handle<JSFunction> closure_;
1856 #endif
1857 };
1858
1859
1860 class HEnvironmentMarker final : public HTemplateInstruction<1> {
1861 public:
1862 enum Kind { BIND, LOOKUP };
1863
1864 DECLARE_INSTRUCTION_FACTORY_P2(HEnvironmentMarker, Kind, int);
1865
1866 Kind kind() const { return kind_; }
1867 int index() const { return index_; }
1868 HSimulate* next_simulate() { return next_simulate_; }
1869 void set_next_simulate(HSimulate* simulate) {
1870 next_simulate_ = simulate;
1871 }
1872
1873 Representation RequiredInputRepresentation(int index) override {
1874 return Representation::None();
1875 }
1876
1877 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1878
1879 #ifdef DEBUG
1880 void set_closure(Handle<JSFunction> closure) {
1881 DCHECK(closure_.is_null());
1882 DCHECK(!closure.is_null());
1883 closure_ = closure;
1884 }
1885 Handle<JSFunction> closure() const { return closure_; }
1886 #endif
1887
1888 DECLARE_CONCRETE_INSTRUCTION(EnvironmentMarker);
1889
1890 private:
1891 HEnvironmentMarker(Kind kind, int index)
1892 : kind_(kind), index_(index), next_simulate_(NULL) { }
1893
1894 Kind kind_;
1895 int index_;
1896 HSimulate* next_simulate_;
1897
1898 #ifdef DEBUG
1899 Handle<JSFunction> closure_;
1900 #endif
1901 };
1902
1903
1904 class HStackCheck final : public HTemplateInstruction<1> {
1905 public:
1906 enum Type {
1907 kFunctionEntry,
1908 kBackwardsBranch
1909 };
1910
1911 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HStackCheck, Type);
1912
1913 HValue* context() { return OperandAt(0); }
1914
1915 Representation RequiredInputRepresentation(int index) override {
1916 return Representation::Tagged();
1917 }
1918
1919 void Eliminate() {
1920 // The stack check eliminator might try to eliminate the same stack
1921 // check instruction multiple times.
1922 if (IsLinked()) {
1923 DeleteAndReplaceWith(NULL);
1924 }
1925 }
1926
1927 bool is_function_entry() { return type_ == kFunctionEntry; }
1928 bool is_backwards_branch() { return type_ == kBackwardsBranch; }
1929
1930 DECLARE_CONCRETE_INSTRUCTION(StackCheck)
1931
1932 private:
1933 HStackCheck(HValue* context, Type type) : type_(type) {
1934 SetOperandAt(0, context);
1935 SetChangesFlag(kNewSpacePromotion);
1936 }
1937
1938 Type type_;
1939 };
1940
1941
1942 enum InliningKind {
1943 NORMAL_RETURN, // Drop the function from the environment on return.
1944 CONSTRUCT_CALL_RETURN, // Either use allocated receiver or return value.
1945 GETTER_CALL_RETURN, // Returning from a getter, need to restore context.
1946 SETTER_CALL_RETURN // Use the RHS of the assignment as the return value.
1947 };
1948
1949
1950 class HArgumentsObject;
1951 class HConstant;
1952
1953
1954 class HEnterInlined final : public HTemplateInstruction<0> {
1955 public:
1956 static HEnterInlined* New(Isolate* isolate, Zone* zone, HValue* context,
1957 BailoutId return_id, Handle<JSFunction> closure,
1958 HConstant* closure_context, int arguments_count,
1959 FunctionLiteral* function,
1960 InliningKind inlining_kind, Variable* arguments_var,
1961 HArgumentsObject* arguments_object) {
1962 return new (zone) HEnterInlined(return_id, closure, closure_context,
1963 arguments_count, function, inlining_kind,
1964 arguments_var, arguments_object, zone);
1965 }
1966
1967 void RegisterReturnTarget(HBasicBlock* return_target, Zone* zone);
1968 ZoneList<HBasicBlock*>* return_targets() { return &return_targets_; }
1969
1970 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1971
1972 Handle<SharedFunctionInfo> shared() const { return shared_; }
1973 Handle<JSFunction> closure() const { return closure_; }
1974 HConstant* closure_context() const { return closure_context_; }
1975 int arguments_count() const { return arguments_count_; }
1976 bool arguments_pushed() const { return arguments_pushed_; }
1977 void set_arguments_pushed() { arguments_pushed_ = true; }
1978 FunctionLiteral* function() const { return function_; }
1979 InliningKind inlining_kind() const { return inlining_kind_; }
1980 BailoutId ReturnId() const { return return_id_; }
1981 int inlining_id() const { return inlining_id_; }
1982 void set_inlining_id(int inlining_id) { inlining_id_ = inlining_id; }
1983
1984 Representation RequiredInputRepresentation(int index) override {
1985 return Representation::None();
1986 }
1987
1988 Variable* arguments_var() { return arguments_var_; }
1989 HArgumentsObject* arguments_object() { return arguments_object_; }
1990
1991 DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
1992
1993 private:
1994 HEnterInlined(BailoutId return_id, Handle<JSFunction> closure,
1995 HConstant* closure_context, int arguments_count,
1996 FunctionLiteral* function, InliningKind inlining_kind,
1997 Variable* arguments_var, HArgumentsObject* arguments_object,
1998 Zone* zone)
1999 : return_id_(return_id),
2000 shared_(handle(closure->shared())),
2001 closure_(closure),
2002 closure_context_(closure_context),
2003 arguments_count_(arguments_count),
2004 arguments_pushed_(false),
2005 function_(function),
2006 inlining_kind_(inlining_kind),
2007 inlining_id_(0),
2008 arguments_var_(arguments_var),
2009 arguments_object_(arguments_object),
2010 return_targets_(2, zone) {}
2011
2012 BailoutId return_id_;
2013 Handle<SharedFunctionInfo> shared_;
2014 Handle<JSFunction> closure_;
2015 HConstant* closure_context_;
2016 int arguments_count_;
2017 bool arguments_pushed_;
2018 FunctionLiteral* function_;
2019 InliningKind inlining_kind_;
2020 int inlining_id_;
2021 Variable* arguments_var_;
2022 HArgumentsObject* arguments_object_;
2023 ZoneList<HBasicBlock*> return_targets_;
2024 };
2025
2026
2027 class HLeaveInlined final : public HTemplateInstruction<0> {
2028 public:
2029 HLeaveInlined(HEnterInlined* entry,
2030 int drop_count)
2031 : entry_(entry),
2032 drop_count_(drop_count) { }
2033
2034 Representation RequiredInputRepresentation(int index) override {
2035 return Representation::None();
2036 }
2037
2038 int argument_delta() const override {
2039 return entry_->arguments_pushed() ? -drop_count_ : 0;
2040 }
2041
2042 DECLARE_CONCRETE_INSTRUCTION(LeaveInlined)
2043
2044 private:
2045 HEnterInlined* entry_;
2046 int drop_count_;
2047 };
2048
2049
2050 class HPushArguments final : public HInstruction {
2051 public:
2052 static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context) {
2053 return new(zone) HPushArguments(zone);
2054 }
2055 static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
2056 HValue* arg1) {
2057 HPushArguments* instr = new(zone) HPushArguments(zone);
2058 instr->AddInput(arg1);
2059 return instr;
2060 }
2061 static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
2062 HValue* arg1, HValue* arg2) {
2063 HPushArguments* instr = new(zone) HPushArguments(zone);
2064 instr->AddInput(arg1);
2065 instr->AddInput(arg2);
2066 return instr;
2067 }
2068 static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
2069 HValue* arg1, HValue* arg2, HValue* arg3) {
2070 HPushArguments* instr = new(zone) HPushArguments(zone);
2071 instr->AddInput(arg1);
2072 instr->AddInput(arg2);
2073 instr->AddInput(arg3);
2074 return instr;
2075 }
2076 static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
2077 HValue* arg1, HValue* arg2, HValue* arg3,
2078 HValue* arg4) {
2079 HPushArguments* instr = new(zone) HPushArguments(zone);
2080 instr->AddInput(arg1);
2081 instr->AddInput(arg2);
2082 instr->AddInput(arg3);
2083 instr->AddInput(arg4);
2084 return instr;
2085 }
2086
2087 Representation RequiredInputRepresentation(int index) override {
2088 return Representation::Tagged();
2089 }
2090
2091 int argument_delta() const override { return inputs_.length(); }
2092 HValue* argument(int i) { return OperandAt(i); }
2093
2094 int OperandCount() const final { return inputs_.length(); }
2095 HValue* OperandAt(int i) const final { return inputs_[i]; }
2096
2097 void AddInput(HValue* value);
2098
2099 DECLARE_CONCRETE_INSTRUCTION(PushArguments)
2100
2101 protected:
2102 void InternalSetOperandAt(int i, HValue* value) final { inputs_[i] = value; }
2103
2104 private:
2105 explicit HPushArguments(Zone* zone)
2106 : HInstruction(HType::Tagged()), inputs_(4, zone) {
2107 set_representation(Representation::Tagged());
2108 }
2109
2110 ZoneList<HValue*> inputs_;
2111 };
2112
2113
2114 class HThisFunction final : public HTemplateInstruction<0> {
2115 public:
2116 DECLARE_INSTRUCTION_FACTORY_P0(HThisFunction);
2117
2118 Representation RequiredInputRepresentation(int index) override {
2119 return Representation::None();
2120 }
2121
2122 DECLARE_CONCRETE_INSTRUCTION(ThisFunction)
2123
2124 protected:
2125 bool DataEquals(HValue* other) override { return true; }
2126
2127 private:
2128 HThisFunction() {
2129 set_representation(Representation::Tagged());
2130 SetFlag(kUseGVN);
2131 }
2132
2133 bool IsDeletable() const override { return true; }
2134 };
2135
2136
2137 class HDeclareGlobals final : public HUnaryOperation {
2138 public:
2139 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HDeclareGlobals,
2140 Handle<FixedArray>,
2141 int);
2142
2143 HValue* context() { return OperandAt(0); }
2144 Handle<FixedArray> pairs() const { return pairs_; }
2145 int flags() const { return flags_; }
2146
2147 DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals)
2148
2149 Representation RequiredInputRepresentation(int index) override {
2150 return Representation::Tagged();
2151 }
2152
2153 private:
2154 HDeclareGlobals(HValue* context,
2155 Handle<FixedArray> pairs,
2156 int flags)
2157 : HUnaryOperation(context),
2158 pairs_(pairs),
2159 flags_(flags) {
2160 set_representation(Representation::Tagged());
2161 SetAllSideEffects();
2162 }
2163
2164 Handle<FixedArray> pairs_;
2165 int flags_;
2166 };
2167
2168
2169 template <int V>
2170 class HCall : public HTemplateInstruction<V> {
2171 public:
2172 // The argument count includes the receiver.
2173 explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
2174 this->set_representation(Representation::Tagged());
2175 this->SetAllSideEffects();
2176 }
2177
2178 HType CalculateInferredType() final { return HType::Tagged(); }
2179
2180 virtual int argument_count() const {
2181 return argument_count_;
2182 }
2183
2184 int argument_delta() const override { return -argument_count(); }
2185
2186 private:
2187 int argument_count_;
2188 };
2189
2190
2191 class HUnaryCall : public HCall<1> {
2192 public:
2193 HUnaryCall(HValue* value, int argument_count)
2194 : HCall<1>(argument_count) {
2195 SetOperandAt(0, value);
2196 }
2197
2198 Representation RequiredInputRepresentation(int index) final {
2199 return Representation::Tagged();
2200 }
2201
2202 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
2203
2204 HValue* value() const { return OperandAt(0); }
2205 };
2206
2207
2208 class HBinaryCall : public HCall<2> {
2209 public:
2210 HBinaryCall(HValue* first, HValue* second, int argument_count)
2211 : HCall<2>(argument_count) {
2212 SetOperandAt(0, first);
2213 SetOperandAt(1, second);
2214 }
2215
2216 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
2217
2218 Representation RequiredInputRepresentation(int index) final {
2219 return Representation::Tagged();
2220 }
2221
2222 HValue* first() const { return OperandAt(0); }
2223 HValue* second() const { return OperandAt(1); }
2224 };
2225
2226
2227 class HCallJSFunction final : public HCall<1> {
2228 public:
2229 static HCallJSFunction* New(Isolate* isolate, Zone* zone, HValue* context,
2230 HValue* function, int argument_count);
2231
2232 HValue* function() const { return OperandAt(0); }
2233
2234 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
2235
2236 Representation RequiredInputRepresentation(int index) final {
2237 DCHECK(index == 0);
2238 return Representation::Tagged();
2239 }
2240
2241 bool HasStackCheck() final { return has_stack_check_; }
2242
2243 DECLARE_CONCRETE_INSTRUCTION(CallJSFunction)
2244
2245 private:
2246 // The argument count includes the receiver.
2247 HCallJSFunction(HValue* function,
2248 int argument_count,
2249 bool has_stack_check)
2250 : HCall<1>(argument_count),
2251 has_stack_check_(has_stack_check) {
2252 SetOperandAt(0, function);
2253 }
2254
2255 bool has_stack_check_;
2256 };
2257
2258
2259 enum CallMode { NORMAL_CALL, TAIL_CALL };
2260
2261
2262 class HCallWithDescriptor final : public HInstruction {
2263 public:
2264 static HCallWithDescriptor* New(Isolate* isolate, Zone* zone, HValue* context,
2265 HValue* target, int argument_count,
2266 CallInterfaceDescriptor descriptor,
2267 const Vector<HValue*>& operands,
2268 CallMode call_mode = NORMAL_CALL) {
2269 HCallWithDescriptor* res = new (zone) HCallWithDescriptor(
2270 target, argument_count, descriptor, operands, call_mode, zone);
2271 DCHECK(operands.length() == res->GetParameterCount());
2272 return res;
2273 }
2274
2275 int OperandCount() const final { return values_.length(); }
2276 HValue* OperandAt(int index) const final { return values_[index]; }
2277
2278 Representation RequiredInputRepresentation(int index) final {
2279 if (index == 0 || index == 1) {
2280 // Target + context
2281 return Representation::Tagged();
2282 } else {
2283 int par_index = index - 2;
2284 DCHECK(par_index < GetParameterCount());
2285 return RepresentationFromType(descriptor_.GetParameterType(par_index));
2286 }
2287 }
2288
2289 DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor)
2290
2291 HType CalculateInferredType() final { return HType::Tagged(); }
2292
2293 bool IsTailCall() const { return call_mode_ == TAIL_CALL; }
2294
2295 virtual int argument_count() const {
2296 return argument_count_;
2297 }
2298
2299 int argument_delta() const override { return -argument_count_; }
2300
2301 CallInterfaceDescriptor descriptor() const { return descriptor_; }
2302
2303 HValue* target() {
2304 return OperandAt(0);
2305 }
2306
2307 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
2308
2309 private:
2310 // The argument count includes the receiver.
2311 HCallWithDescriptor(HValue* target, int argument_count,
2312 CallInterfaceDescriptor descriptor,
2313 const Vector<HValue*>& operands, CallMode call_mode,
2314 Zone* zone)
2315 : descriptor_(descriptor),
2316 values_(GetParameterCount() + 1, zone),
2317 argument_count_(argument_count),
2318 call_mode_(call_mode) {
2319 // We can only tail call without any stack arguments.
2320 DCHECK(call_mode != TAIL_CALL || argument_count == 0);
2321 AddOperand(target, zone);
2322 for (int i = 0; i < operands.length(); i++) {
2323 AddOperand(operands[i], zone);
2324 }
2325 this->set_representation(Representation::Tagged());
2326 this->SetAllSideEffects();
2327 }
2328
2329 void AddOperand(HValue* v, Zone* zone) {
2330 values_.Add(NULL, zone);
2331 SetOperandAt(values_.length() - 1, v);
2332 }
2333
2334 int GetParameterCount() const {
2335 return descriptor_.GetRegisterParameterCount() + 1;
2336 }
2337
2338 void InternalSetOperandAt(int index, HValue* value) final {
2339 values_[index] = value;
2340 }
2341
2342 CallInterfaceDescriptor descriptor_;
2343 ZoneList<HValue*> values_;
2344 int argument_count_;
2345 CallMode call_mode_;
2346 };
2347
2348
2349 class HInvokeFunction final : public HBinaryCall {
2350 public:
2351 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInvokeFunction, HValue*, int);
2352
2353 HInvokeFunction(HValue* context,
2354 HValue* function,
2355 Handle<JSFunction> known_function,
2356 int argument_count)
2357 : HBinaryCall(context, function, argument_count),
2358 known_function_(known_function) {
2359 formal_parameter_count_ =
2360 known_function.is_null()
2361 ? 0
2362 : known_function->shared()->internal_formal_parameter_count();
2363 has_stack_check_ = !known_function.is_null() &&
2364 (known_function->code()->kind() == Code::FUNCTION ||
2365 known_function->code()->kind() == Code::OPTIMIZED_FUNCTION);
2366 }
2367
2368 static HInvokeFunction* New(Isolate* isolate, Zone* zone, HValue* context,
2369 HValue* function,
2370 Handle<JSFunction> known_function,
2371 int argument_count) {
2372 return new(zone) HInvokeFunction(context, function,
2373 known_function, argument_count);
2374 }
2375
2376 HValue* context() { return first(); }
2377 HValue* function() { return second(); }
2378 Handle<JSFunction> known_function() { return known_function_; }
2379 int formal_parameter_count() const { return formal_parameter_count_; }
2380
2381 bool HasStackCheck() final { return has_stack_check_; }
2382
2383 DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
2384
2385 private:
2386 HInvokeFunction(HValue* context, HValue* function, int argument_count)
2387 : HBinaryCall(context, function, argument_count),
2388 has_stack_check_(false) {
2389 }
2390
2391 Handle<JSFunction> known_function_;
2392 int formal_parameter_count_;
2393 bool has_stack_check_;
2394 };
2395
2396
2397 class HCallFunction final : public HBinaryCall {
2398 public:
2399 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallFunction, HValue*, int);
2400 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(
2401 HCallFunction, HValue*, int, CallFunctionFlags);
2402
2403 HValue* context() const { return first(); }
2404 HValue* function() const { return second(); }
2405 CallFunctionFlags function_flags() const { return function_flags_; }
2406
2407 FeedbackVectorSlot slot() const { return slot_; }
2408 Handle<TypeFeedbackVector> feedback_vector() const {
2409 return feedback_vector_;
2410 }
2411 bool HasVectorAndSlot() const { return !feedback_vector_.is_null(); }
2412 void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
2413 FeedbackVectorSlot slot) {
2414 feedback_vector_ = vector;
2415 slot_ = slot;
2416 }
2417
2418 DECLARE_CONCRETE_INSTRUCTION(CallFunction)
2419
2420 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
2421
2422 int argument_delta() const override { return -argument_count(); }
2423
2424 private:
2425 HCallFunction(HValue* context, HValue* function, int argument_count,
2426 CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS)
2427 : HBinaryCall(context, function, argument_count),
2428 function_flags_(flags) {}
2429 CallFunctionFlags function_flags_;
2430 Handle<TypeFeedbackVector> feedback_vector_;
2431 FeedbackVectorSlot slot_;
2432 };
2433
2434
2435 class HCallNew final : public HBinaryCall {
2436 public:
2437 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallNew, HValue*, int);
2438
2439 HValue* context() { return first(); }
2440 HValue* constructor() { return second(); }
2441
2442 DECLARE_CONCRETE_INSTRUCTION(CallNew)
2443
2444 private:
2445 HCallNew(HValue* context, HValue* constructor, int argument_count)
2446 : HBinaryCall(context, constructor, argument_count) {}
2447 };
2448
2449
2450 class HCallNewArray final : public HBinaryCall {
2451 public:
2452 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HCallNewArray, HValue*, int,
2453 ElementsKind,
2454 Handle<AllocationSite>);
2455
2456 HValue* context() { return first(); }
2457 HValue* constructor() { return second(); }
2458
2459 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
2460
2461 ElementsKind elements_kind() const { return elements_kind_; }
2462 Handle<AllocationSite> site() const { return site_; }
2463
2464 DECLARE_CONCRETE_INSTRUCTION(CallNewArray)
2465
2466 private:
2467 HCallNewArray(HValue* context, HValue* constructor, int argument_count,
2468 ElementsKind elements_kind, Handle<AllocationSite> site)
2469 : HBinaryCall(context, constructor, argument_count),
2470 elements_kind_(elements_kind),
2471 site_(site) {}
2472
2473 ElementsKind elements_kind_;
2474 Handle<AllocationSite> site_;
2475 };
2476
2477
2478 class HCallRuntime final : public HCall<1> {
2479 public:
2480 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallRuntime,
2481 const Runtime::Function*, int);
2482
2483 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
2484
2485 HValue* context() { return OperandAt(0); }
2486 const Runtime::Function* function() const { return c_function_; }
2487 SaveFPRegsMode save_doubles() const { return save_doubles_; }
2488 void set_save_doubles(SaveFPRegsMode save_doubles) {
2489 save_doubles_ = save_doubles;
2490 }
2491
2492 Representation RequiredInputRepresentation(int index) override {
2493 return Representation::Tagged();
2494 }
2495
2496 DECLARE_CONCRETE_INSTRUCTION(CallRuntime)
2497
2498 private:
2499 HCallRuntime(HValue* context, const Runtime::Function* c_function,
2500 int argument_count)
2501 : HCall<1>(argument_count),
2502 c_function_(c_function),
2503 save_doubles_(kDontSaveFPRegs) {
2504 SetOperandAt(0, context);
2505 }
2506
2507 const Runtime::Function* c_function_;
2508 SaveFPRegsMode save_doubles_;
2509 };
2510
2511
2512 class HMapEnumLength final : public HUnaryOperation {
2513 public:
2514 DECLARE_INSTRUCTION_FACTORY_P1(HMapEnumLength, HValue*);
2515
2516 Representation RequiredInputRepresentation(int index) override {
2517 return Representation::Tagged();
2518 }
2519
2520 DECLARE_CONCRETE_INSTRUCTION(MapEnumLength)
2521
2522 protected:
2523 bool DataEquals(HValue* other) override { return true; }
2524
2525 private:
2526 explicit HMapEnumLength(HValue* value)
2527 : HUnaryOperation(value, HType::Smi()) {
2528 set_representation(Representation::Smi());
2529 SetFlag(kUseGVN);
2530 SetDependsOnFlag(kMaps);
2531 }
2532
2533 bool IsDeletable() const override { return true; }
2534 };
2535
2536
2537 class HUnaryMathOperation final : public HTemplateInstruction<2> {
2538 public:
2539 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
2540 HValue* value, BuiltinFunctionId op);
2541
2542 HValue* context() const { return OperandAt(0); }
2543 HValue* value() const { return OperandAt(1); }
2544
2545 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
2546
2547 Representation RequiredInputRepresentation(int index) override {
2548 if (index == 0) {
2549 return Representation::Tagged();
2550 } else {
2551 switch (op_) {
2552 case kMathFloor:
2553 case kMathRound:
2554 case kMathFround:
2555 case kMathSqrt:
2556 case kMathPowHalf:
2557 case kMathLog:
2558 case kMathExp:
2559 return Representation::Double();
2560 case kMathAbs:
2561 return representation();
2562 case kMathClz32:
2563 return Representation::Integer32();
2564 default:
2565 UNREACHABLE();
2566 return Representation::None();
2567 }
2568 }
2569 }
2570
2571 Range* InferRange(Zone* zone) override;
2572
2573 HValue* Canonicalize() override;
2574 Representation RepresentationFromUses() override;
2575 Representation RepresentationFromInputs() override;
2576
2577 BuiltinFunctionId op() const { return op_; }
2578 const char* OpName() const;
2579
2580 DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)
2581
2582 protected:
2583 bool DataEquals(HValue* other) override {
2584 HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
2585 return op_ == b->op();
2586 }
2587
2588 private:
2589 // Indicates if we support a double (and int32) output for Math.floor and
2590 // Math.round.
2591 bool SupportsFlexibleFloorAndRound() const {
2592 #ifdef V8_TARGET_ARCH_ARM64
2593 // TODO(rmcilroy): Re-enable this for Arm64 once http://crbug.com/476477 is
2594 // fixed.
2595 return false;
2596 #else
2597 return false;
2598 #endif
2599 }
2600 HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
2601 : HTemplateInstruction<2>(HType::TaggedNumber()), op_(op) {
2602 SetOperandAt(0, context);
2603 SetOperandAt(1, value);
2604 switch (op) {
2605 case kMathFloor:
2606 case kMathRound:
2607 if (SupportsFlexibleFloorAndRound()) {
2608 SetFlag(kFlexibleRepresentation);
2609 } else {
2610 set_representation(Representation::Integer32());
2611 }
2612 break;
2613 case kMathClz32:
2614 set_representation(Representation::Integer32());
2615 break;
2616 case kMathAbs:
2617 // Not setting representation here: it is None intentionally.
2618 SetFlag(kFlexibleRepresentation);
2619 // TODO(svenpanne) This flag is actually only needed if representation()
2620 // is tagged, and not when it is an unboxed double or unboxed integer.
2621 SetChangesFlag(kNewSpacePromotion);
2622 break;
2623 case kMathFround:
2624 case kMathLog:
2625 case kMathExp:
2626 case kMathSqrt:
2627 case kMathPowHalf:
2628 set_representation(Representation::Double());
2629 break;
2630 default:
2631 UNREACHABLE();
2632 }
2633 SetFlag(kUseGVN);
2634 SetFlag(kAllowUndefinedAsNaN);
2635 }
2636
2637 bool IsDeletable() const override {
2638 // TODO(crankshaft): This should be true, however the semantics of this
2639 // instruction also include the ToNumber conversion that is mentioned in the
2640 // spec, which is of course observable.
2641 return false;
2642 }
2643
2644 HValue* SimplifiedDividendForMathFloorOfDiv(HDiv* hdiv);
2645 HValue* SimplifiedDivisorForMathFloorOfDiv(HDiv* hdiv);
2646
2647 BuiltinFunctionId op_;
2648 };
2649
2650
2651 class HLoadRoot final : public HTemplateInstruction<0> {
2652 public:
2653 DECLARE_INSTRUCTION_FACTORY_P1(HLoadRoot, Heap::RootListIndex);
2654 DECLARE_INSTRUCTION_FACTORY_P2(HLoadRoot, Heap::RootListIndex, HType);
2655
2656 Representation RequiredInputRepresentation(int index) override {
2657 return Representation::None();
2658 }
2659
2660 Heap::RootListIndex index() const { return index_; }
2661
2662 DECLARE_CONCRETE_INSTRUCTION(LoadRoot)
2663
2664 protected:
2665 bool DataEquals(HValue* other) override {
2666 HLoadRoot* b = HLoadRoot::cast(other);
2667 return index_ == b->index_;
2668 }
2669
2670 private:
2671 explicit HLoadRoot(Heap::RootListIndex index, HType type = HType::Tagged())
2672 : HTemplateInstruction<0>(type), index_(index) {
2673 SetFlag(kUseGVN);
2674 // TODO(bmeurer): We'll need kDependsOnRoots once we add the
2675 // corresponding HStoreRoot instruction.
2676 SetDependsOnFlag(kCalls);
2677 set_representation(Representation::Tagged());
2678 }
2679
2680 bool IsDeletable() const override { return true; }
2681
2682 const Heap::RootListIndex index_;
2683 };
2684
2685
2686 class HCheckMaps final : public HTemplateInstruction<2> {
2687 public:
2688 static HCheckMaps* New(Isolate* isolate, Zone* zone, HValue* context,
2689 HValue* value, Handle<Map> map,
2690 HValue* typecheck = NULL) {
2691 return new(zone) HCheckMaps(value, new(zone) UniqueSet<Map>(
2692 Unique<Map>::CreateImmovable(map), zone), typecheck);
2693 }
2694 static HCheckMaps* New(Isolate* isolate, Zone* zone, HValue* context,
2695 HValue* value, SmallMapList* map_list,
2696 HValue* typecheck = NULL) {
2697 UniqueSet<Map>* maps = new(zone) UniqueSet<Map>(map_list->length(), zone);
2698 for (int i = 0; i < map_list->length(); ++i) {
2699 maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone);
2700 }
2701 return new(zone) HCheckMaps(value, maps, typecheck);
2702 }
2703
2704 bool IsStabilityCheck() const {
2705 return IsStabilityCheckField::decode(bit_field_);
2706 }
2707 void MarkAsStabilityCheck() {
2708 bit_field_ = MapsAreStableField::encode(true) |
2709 HasMigrationTargetField::encode(false) |
2710 IsStabilityCheckField::encode(true);
2711 ClearChangesFlag(kNewSpacePromotion);
2712 ClearDependsOnFlag(kElementsKind);
2713 ClearDependsOnFlag(kMaps);
2714 }
2715
2716 bool HasEscapingOperandAt(int index) override { return false; }
2717 Representation RequiredInputRepresentation(int index) override {
2718 return Representation::Tagged();
2719 }
2720
2721 HType CalculateInferredType() override {
2722 if (value()->type().IsHeapObject()) return value()->type();
2723 return HType::HeapObject();
2724 }
2725
2726 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
2727
2728 HValue* value() const { return OperandAt(0); }
2729 HValue* typecheck() const { return OperandAt(1); }
2730
2731 const UniqueSet<Map>* maps() const { return maps_; }
2732 void set_maps(const UniqueSet<Map>* maps) { maps_ = maps; }
2733
2734 bool maps_are_stable() const {
2735 return MapsAreStableField::decode(bit_field_);
2736 }
2737
2738 bool HasMigrationTarget() const {
2739 return HasMigrationTargetField::decode(bit_field_);
2740 }
2741
2742 HValue* Canonicalize() override;
2743
2744 static HCheckMaps* CreateAndInsertAfter(Zone* zone,
2745 HValue* value,
2746 Unique<Map> map,
2747 bool map_is_stable,
2748 HInstruction* instr) {
2749 return instr->Append(new(zone) HCheckMaps(
2750 value, new(zone) UniqueSet<Map>(map, zone), map_is_stable));
2751 }
2752
2753 static HCheckMaps* CreateAndInsertBefore(Zone* zone,
2754 HValue* value,
2755 const UniqueSet<Map>* maps,
2756 bool maps_are_stable,
2757 HInstruction* instr) {
2758 return instr->Prepend(new(zone) HCheckMaps(value, maps, maps_are_stable));
2759 }
2760
2761 DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
2762
2763 protected:
2764 bool DataEquals(HValue* other) override {
2765 return this->maps()->Equals(HCheckMaps::cast(other)->maps());
2766 }
2767
2768 int RedefinedOperandIndex() override { return 0; }
2769
2770 private:
2771 HCheckMaps(HValue* value, const UniqueSet<Map>* maps, bool maps_are_stable)
2772 : HTemplateInstruction<2>(HType::HeapObject()),
2773 maps_(maps),
2774 bit_field_(HasMigrationTargetField::encode(false) |
2775 IsStabilityCheckField::encode(false) |
2776 MapsAreStableField::encode(maps_are_stable)) {
2777 DCHECK_NE(0, maps->size());
2778 SetOperandAt(0, value);
2779 // Use the object value for the dependency.
2780 SetOperandAt(1, value);
2781 set_representation(Representation::Tagged());
2782 SetFlag(kUseGVN);
2783 SetDependsOnFlag(kMaps);
2784 SetDependsOnFlag(kElementsKind);
2785 }
2786
2787 HCheckMaps(HValue* value, const UniqueSet<Map>* maps, HValue* typecheck)
2788 : HTemplateInstruction<2>(HType::HeapObject()),
2789 maps_(maps),
2790 bit_field_(HasMigrationTargetField::encode(false) |
2791 IsStabilityCheckField::encode(false) |
2792 MapsAreStableField::encode(true)) {
2793 DCHECK_NE(0, maps->size());
2794 SetOperandAt(0, value);
2795 // Use the object value for the dependency if NULL is passed.
2796 SetOperandAt(1, typecheck ? typecheck : value);
2797 set_representation(Representation::Tagged());
2798 SetFlag(kUseGVN);
2799 SetDependsOnFlag(kMaps);
2800 SetDependsOnFlag(kElementsKind);
2801 for (int i = 0; i < maps->size(); ++i) {
2802 Handle<Map> map = maps->at(i).handle();
2803 if (map->is_migration_target()) {
2804 bit_field_ = HasMigrationTargetField::update(bit_field_, true);
2805 }
2806 if (!map->is_stable()) {
2807 bit_field_ = MapsAreStableField::update(bit_field_, false);
2808 }
2809 }
2810 if (HasMigrationTarget()) SetChangesFlag(kNewSpacePromotion);
2811 }
2812
2813 class HasMigrationTargetField : public BitField<bool, 0, 1> {};
2814 class IsStabilityCheckField : public BitField<bool, 1, 1> {};
2815 class MapsAreStableField : public BitField<bool, 2, 1> {};
2816
2817 const UniqueSet<Map>* maps_;
2818 uint32_t bit_field_;
2819 };
2820
2821
2822 class HCheckValue final : public HUnaryOperation {
2823 public:
2824 static HCheckValue* New(Isolate* isolate, Zone* zone, HValue* context,
2825 HValue* value, Handle<JSFunction> func) {
2826 bool in_new_space = isolate->heap()->InNewSpace(*func);
2827 // NOTE: We create an uninitialized Unique and initialize it later.
2828 // This is because a JSFunction can move due to GC during graph creation.
2829 // TODO(titzer): This is a migration crutch. Replace with some kind of
2830 // Uniqueness scope later.
2831 Unique<JSFunction> target = Unique<JSFunction>::CreateUninitialized(func);
2832 HCheckValue* check = new(zone) HCheckValue(value, target, in_new_space);
2833 return check;
2834 }
2835 static HCheckValue* New(Isolate* isolate, Zone* zone, HValue* context,
2836 HValue* value, Unique<HeapObject> target,
2837 bool object_in_new_space) {
2838 return new(zone) HCheckValue(value, target, object_in_new_space);
2839 }
2840
2841 void FinalizeUniqueness() override {
2842 object_ = Unique<HeapObject>(object_.handle());
2843 }
2844
2845 Representation RequiredInputRepresentation(int index) override {
2846 return Representation::Tagged();
2847 }
2848 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
2849
2850 HValue* Canonicalize() override;
2851
2852 #ifdef DEBUG
2853 void Verify() override;
2854 #endif
2855
2856 Unique<HeapObject> object() const { return object_; }
2857 bool object_in_new_space() const { return object_in_new_space_; }
2858
2859 DECLARE_CONCRETE_INSTRUCTION(CheckValue)
2860
2861 protected:
2862 bool DataEquals(HValue* other) override {
2863 HCheckValue* b = HCheckValue::cast(other);
2864 return object_ == b->object_;
2865 }
2866
2867 private:
2868 HCheckValue(HValue* value, Unique<HeapObject> object,
2869 bool object_in_new_space)
2870 : HUnaryOperation(value, value->type()),
2871 object_(object),
2872 object_in_new_space_(object_in_new_space) {
2873 set_representation(Representation::Tagged());
2874 SetFlag(kUseGVN);
2875 }
2876
2877 Unique<HeapObject> object_;
2878 bool object_in_new_space_;
2879 };
2880
2881
2882 class HCheckInstanceType final : public HUnaryOperation {
2883 public:
2884 enum Check {
2885 IS_SPEC_OBJECT,
2886 IS_JS_ARRAY,
2887 IS_JS_DATE,
2888 IS_STRING,
2889 IS_INTERNALIZED_STRING,
2890 LAST_INTERVAL_CHECK = IS_JS_DATE
2891 };
2892
2893 DECLARE_INSTRUCTION_FACTORY_P2(HCheckInstanceType, HValue*, Check);
2894
2895 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
2896
2897 Representation RequiredInputRepresentation(int index) override {
2898 return Representation::Tagged();
2899 }
2900
2901 HType CalculateInferredType() override {
2902 switch (check_) {
2903 case IS_SPEC_OBJECT: return HType::JSObject();
2904 case IS_JS_ARRAY: return HType::JSArray();
2905 case IS_JS_DATE:
2906 return HType::JSObject();
2907 case IS_STRING: return HType::String();
2908 case IS_INTERNALIZED_STRING: return HType::String();
2909 }
2910 UNREACHABLE();
2911 return HType::Tagged();
2912 }
2913
2914 HValue* Canonicalize() override;
2915
2916 bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
2917 void GetCheckInterval(InstanceType* first, InstanceType* last);
2918 void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);
2919
2920 Check check() const { return check_; }
2921
2922 DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)
2923
2924 protected:
2925 // TODO(ager): It could be nice to allow the ommision of instance
2926 // type checks if we have already performed an instance type check
2927 // with a larger range.
2928 bool DataEquals(HValue* other) override {
2929 HCheckInstanceType* b = HCheckInstanceType::cast(other);
2930 return check_ == b->check_;
2931 }
2932
2933 int RedefinedOperandIndex() override { return 0; }
2934
2935 private:
2936 const char* GetCheckName() const;
2937
2938 HCheckInstanceType(HValue* value, Check check)
2939 : HUnaryOperation(value, HType::HeapObject()), check_(check) {
2940 set_representation(Representation::Tagged());
2941 SetFlag(kUseGVN);
2942 }
2943
2944 const Check check_;
2945 };
2946
2947
2948 class HCheckSmi final : public HUnaryOperation {
2949 public:
2950 DECLARE_INSTRUCTION_FACTORY_P1(HCheckSmi, HValue*);
2951
2952 Representation RequiredInputRepresentation(int index) override {
2953 return Representation::Tagged();
2954 }
2955
2956 HValue* Canonicalize() override {
2957 HType value_type = value()->type();
2958 if (value_type.IsSmi()) {
2959 return NULL;
2960 }
2961 return this;
2962 }
2963
2964 DECLARE_CONCRETE_INSTRUCTION(CheckSmi)
2965
2966 protected:
2967 bool DataEquals(HValue* other) override { return true; }
2968
2969 private:
2970 explicit HCheckSmi(HValue* value) : HUnaryOperation(value, HType::Smi()) {
2971 set_representation(Representation::Smi());
2972 SetFlag(kUseGVN);
2973 }
2974 };
2975
2976
2977 class HCheckArrayBufferNotNeutered final : public HUnaryOperation {
2978 public:
2979 DECLARE_INSTRUCTION_FACTORY_P1(HCheckArrayBufferNotNeutered, HValue*);
2980
2981 bool HasEscapingOperandAt(int index) override { return false; }
2982 Representation RequiredInputRepresentation(int index) override {
2983 return Representation::Tagged();
2984 }
2985
2986 HType CalculateInferredType() override {
2987 if (value()->type().IsHeapObject()) return value()->type();
2988 return HType::HeapObject();
2989 }
2990
2991 DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered)
2992
2993 protected:
2994 bool DataEquals(HValue* other) override { return true; }
2995 int RedefinedOperandIndex() override { return 0; }
2996
2997 private:
2998 explicit HCheckArrayBufferNotNeutered(HValue* value)
2999 : HUnaryOperation(value) {
3000 set_representation(Representation::Tagged());
3001 SetFlag(kUseGVN);
3002 SetDependsOnFlag(kCalls);
3003 }
3004 };
3005
3006
3007 class HCheckHeapObject final : public HUnaryOperation {
3008 public:
3009 DECLARE_INSTRUCTION_FACTORY_P1(HCheckHeapObject, HValue*);
3010
3011 bool HasEscapingOperandAt(int index) override { return false; }
3012 Representation RequiredInputRepresentation(int index) override {
3013 return Representation::Tagged();
3014 }
3015
3016 HType CalculateInferredType() override {
3017 if (value()->type().IsHeapObject()) return value()->type();
3018 return HType::HeapObject();
3019 }
3020
3021 #ifdef DEBUG
3022 void Verify() override;
3023 #endif
3024
3025 HValue* Canonicalize() override {
3026 return value()->type().IsHeapObject() ? NULL : this;
3027 }
3028
3029 DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject)
3030
3031 protected:
3032 bool DataEquals(HValue* other) override { return true; }
3033
3034 private:
3035 explicit HCheckHeapObject(HValue* value) : HUnaryOperation(value) {
3036 set_representation(Representation::Tagged());
3037 SetFlag(kUseGVN);
3038 }
3039 };
3040
3041
3042 class InductionVariableData;
3043
3044
3045 struct InductionVariableLimitUpdate {
3046 InductionVariableData* updated_variable;
3047 HValue* limit;
3048 bool limit_is_upper;
3049 bool limit_is_included;
3050
3051 InductionVariableLimitUpdate()
3052 : updated_variable(NULL), limit(NULL),
3053 limit_is_upper(false), limit_is_included(false) {}
3054 };
3055
3056
3057 class HBoundsCheck;
3058 class HPhi;
3059 class HBitwise;
3060
3061
3062 class InductionVariableData final : public ZoneObject {
3063 public:
3064 class InductionVariableCheck : public ZoneObject {
3065 public:
3066 HBoundsCheck* check() { return check_; }
3067 InductionVariableCheck* next() { return next_; }
3068 bool HasUpperLimit() { return upper_limit_ >= 0; }
3069 int32_t upper_limit() {
3070 DCHECK(HasUpperLimit());
3071 return upper_limit_;
3072 }
3073 void set_upper_limit(int32_t upper_limit) {
3074 upper_limit_ = upper_limit;
3075 }
3076
3077 bool processed() { return processed_; }
3078 void set_processed() { processed_ = true; }
3079
3080 InductionVariableCheck(HBoundsCheck* check,
3081 InductionVariableCheck* next,
3082 int32_t upper_limit = kNoLimit)
3083 : check_(check), next_(next), upper_limit_(upper_limit),
3084 processed_(false) {}
3085
3086 private:
3087 HBoundsCheck* check_;
3088 InductionVariableCheck* next_;
3089 int32_t upper_limit_;
3090 bool processed_;
3091 };
3092
3093 class ChecksRelatedToLength : public ZoneObject {
3094 public:
3095 HValue* length() { return length_; }
3096 ChecksRelatedToLength* next() { return next_; }
3097 InductionVariableCheck* checks() { return checks_; }
3098
3099 void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
3100 void CloseCurrentBlock();
3101
3102 ChecksRelatedToLength(HValue* length, ChecksRelatedToLength* next)
3103 : length_(length), next_(next), checks_(NULL),
3104 first_check_in_block_(NULL),
3105 added_index_(NULL),
3106 added_constant_(NULL),
3107 current_and_mask_in_block_(0),
3108 current_or_mask_in_block_(0) {}
3109
3110 private:
3111 void UseNewIndexInCurrentBlock(Token::Value token,
3112 int32_t mask,
3113 HValue* index_base,
3114 HValue* context);
3115
3116 HBoundsCheck* first_check_in_block() { return first_check_in_block_; }
3117 HBitwise* added_index() { return added_index_; }
3118 void set_added_index(HBitwise* index) { added_index_ = index; }
3119 HConstant* added_constant() { return added_constant_; }
3120 void set_added_constant(HConstant* constant) { added_constant_ = constant; }
3121 int32_t current_and_mask_in_block() { return current_and_mask_in_block_; }
3122 int32_t current_or_mask_in_block() { return current_or_mask_in_block_; }
3123 int32_t current_upper_limit() { return current_upper_limit_; }
3124
3125 HValue* length_;
3126 ChecksRelatedToLength* next_;
3127 InductionVariableCheck* checks_;
3128
3129 HBoundsCheck* first_check_in_block_;
3130 HBitwise* added_index_;
3131 HConstant* added_constant_;
3132 int32_t current_and_mask_in_block_;
3133 int32_t current_or_mask_in_block_;
3134 int32_t current_upper_limit_;
3135 };
3136
3137 struct LimitFromPredecessorBlock {
3138 InductionVariableData* variable;
3139 Token::Value token;
3140 HValue* limit;
3141 HBasicBlock* other_target;
3142
3143 bool LimitIsValid() { return token != Token::ILLEGAL; }
3144
3145 bool LimitIsIncluded() {
3146 return Token::IsEqualityOp(token) ||
3147 token == Token::GTE || token == Token::LTE;
3148 }
3149 bool LimitIsUpper() {
3150 return token == Token::LTE || token == Token::LT || token == Token::NE;
3151 }
3152
3153 LimitFromPredecessorBlock()
3154 : variable(NULL),
3155 token(Token::ILLEGAL),
3156 limit(NULL),
3157 other_target(NULL) {}
3158 };
3159
3160 static const int32_t kNoLimit = -1;
3161
3162 static InductionVariableData* ExaminePhi(HPhi* phi);
3163 static void ComputeLimitFromPredecessorBlock(
3164 HBasicBlock* block,
3165 LimitFromPredecessorBlock* result);
3166 static bool ComputeInductionVariableLimit(
3167 HBasicBlock* block,
3168 InductionVariableLimitUpdate* additional_limit);
3169
3170 struct BitwiseDecompositionResult {
3171 HValue* base;
3172 int32_t and_mask;
3173 int32_t or_mask;
3174 HValue* context;
3175
3176 BitwiseDecompositionResult()
3177 : base(NULL), and_mask(0), or_mask(0), context(NULL) {}
3178 };
3179 static void DecomposeBitwise(HValue* value,
3180 BitwiseDecompositionResult* result);
3181
3182 void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
3183
3184 bool CheckIfBranchIsLoopGuard(Token::Value token,
3185 HBasicBlock* current_branch,
3186 HBasicBlock* other_branch);
3187
3188 void UpdateAdditionalLimit(InductionVariableLimitUpdate* update);
3189
3190 HPhi* phi() { return phi_; }
3191 HValue* base() { return base_; }
3192 int32_t increment() { return increment_; }
3193 HValue* limit() { return limit_; }
3194 bool limit_included() { return limit_included_; }
3195 HBasicBlock* limit_validity() { return limit_validity_; }
3196 HBasicBlock* induction_exit_block() { return induction_exit_block_; }
3197 HBasicBlock* induction_exit_target() { return induction_exit_target_; }
3198 ChecksRelatedToLength* checks() { return checks_; }
3199 HValue* additional_upper_limit() { return additional_upper_limit_; }
3200 bool additional_upper_limit_is_included() {
3201 return additional_upper_limit_is_included_;
3202 }
3203 HValue* additional_lower_limit() { return additional_lower_limit_; }
3204 bool additional_lower_limit_is_included() {
3205 return additional_lower_limit_is_included_;
3206 }
3207
3208 bool LowerLimitIsNonNegativeConstant() {
3209 if (base()->IsInteger32Constant() && base()->GetInteger32Constant() >= 0) {
3210 return true;
3211 }
3212 if (additional_lower_limit() != NULL &&
3213 additional_lower_limit()->IsInteger32Constant() &&
3214 additional_lower_limit()->GetInteger32Constant() >= 0) {
3215 // Ignoring the corner case of !additional_lower_limit_is_included()
3216 // is safe, handling it adds unneeded complexity.
3217 return true;
3218 }
3219 return false;
3220 }
3221
3222 int32_t ComputeUpperLimit(int32_t and_mask, int32_t or_mask);
3223
3224 private:
3225 template <class T> void swap(T* a, T* b) {
3226 T c(*a);
3227 *a = *b;
3228 *b = c;
3229 }
3230
3231 InductionVariableData(HPhi* phi, HValue* base, int32_t increment)
3232 : phi_(phi), base_(IgnoreOsrValue(base)), increment_(increment),
3233 limit_(NULL), limit_included_(false), limit_validity_(NULL),
3234 induction_exit_block_(NULL), induction_exit_target_(NULL),
3235 checks_(NULL),
3236 additional_upper_limit_(NULL),
3237 additional_upper_limit_is_included_(false),
3238 additional_lower_limit_(NULL),
3239 additional_lower_limit_is_included_(false) {}
3240
3241 static int32_t ComputeIncrement(HPhi* phi, HValue* phi_operand);
3242
3243 static HValue* IgnoreOsrValue(HValue* v);
3244 static InductionVariableData* GetInductionVariableData(HValue* v);
3245
3246 HPhi* phi_;
3247 HValue* base_;
3248 int32_t increment_;
3249 HValue* limit_;
3250 bool limit_included_;
3251 HBasicBlock* limit_validity_;
3252 HBasicBlock* induction_exit_block_;
3253 HBasicBlock* induction_exit_target_;
3254 ChecksRelatedToLength* checks_;
3255 HValue* additional_upper_limit_;
3256 bool additional_upper_limit_is_included_;
3257 HValue* additional_lower_limit_;
3258 bool additional_lower_limit_is_included_;
3259 };
3260
3261
3262 class HPhi final : public HValue {
3263 public:
3264 HPhi(int merged_index, Zone* zone)
3265 : inputs_(2, zone), merged_index_(merged_index) {
3266 DCHECK(merged_index >= 0 || merged_index == kInvalidMergedIndex);
3267 SetFlag(kFlexibleRepresentation);
3268 SetFlag(kAllowUndefinedAsNaN);
3269 }
3270
3271 Representation RepresentationFromInputs() override;
3272
3273 Range* InferRange(Zone* zone) override;
3274 virtual void InferRepresentation(HInferRepresentationPhase* h_infer) override;
3275 Representation RequiredInputRepresentation(int index) override {
3276 return representation();
3277 }
3278 Representation KnownOptimalRepresentation() override {
3279 return representation();
3280 }
3281 HType CalculateInferredType() override;
3282 int OperandCount() const override { return inputs_.length(); }
3283 HValue* OperandAt(int index) const override { return inputs_[index]; }
3284 HValue* GetRedundantReplacement();
3285 void AddInput(HValue* value);
3286 bool HasRealUses();
3287
3288 bool IsReceiver() const { return merged_index_ == 0; }
3289 bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; }
3290
3291 SourcePosition position() const override;
3292
3293 int merged_index() const { return merged_index_; }
3294
3295 InductionVariableData* induction_variable_data() {
3296 return induction_variable_data_;
3297 }
3298 bool IsInductionVariable() {
3299 return induction_variable_data_ != NULL;
3300 }
3301 bool IsLimitedInductionVariable() {
3302 return IsInductionVariable() &&
3303 induction_variable_data_->limit() != NULL;
3304 }
3305 void DetectInductionVariable() {
3306 DCHECK(induction_variable_data_ == NULL);
3307 induction_variable_data_ = InductionVariableData::ExaminePhi(this);
3308 }
3309
3310 std::ostream& PrintTo(std::ostream& os) const override; // NOLINT
3311
3312 #ifdef DEBUG
3313 void Verify() override;
3314 #endif
3315
3316 void InitRealUses(int id);
3317 void AddNonPhiUsesFrom(HPhi* other);
3318
3319 Representation representation_from_indirect_uses() const {
3320 return representation_from_indirect_uses_;
3321 }
3322
3323 bool has_type_feedback_from_uses() const {
3324 return has_type_feedback_from_uses_;
3325 }
3326
3327 int phi_id() { return phi_id_; }
3328
3329 static HPhi* cast(HValue* value) {
3330 DCHECK(value->IsPhi());
3331 return reinterpret_cast<HPhi*>(value);
3332 }
3333 Opcode opcode() const override { return HValue::kPhi; }
3334
3335 void SimplifyConstantInputs();
3336
3337 // Marker value representing an invalid merge index.
3338 static const int kInvalidMergedIndex = -1;
3339
3340 protected:
3341 void DeleteFromGraph() override;
3342 void InternalSetOperandAt(int index, HValue* value) override {
3343 inputs_[index] = value;
3344 }
3345
3346 private:
3347 Representation representation_from_non_phi_uses() const {
3348 return representation_from_non_phi_uses_;
3349 }
3350
3351 ZoneList<HValue*> inputs_;
3352 int merged_index_ = 0;
3353
3354 int phi_id_ = -1;
3355 InductionVariableData* induction_variable_data_ = nullptr;
3356
3357 Representation representation_from_indirect_uses_ = Representation::None();
3358 Representation representation_from_non_phi_uses_ = Representation::None();
3359 bool has_type_feedback_from_uses_ = false;
3360
3361 // TODO(titzer): we can't eliminate the receiver for generating backtraces
3362 bool IsDeletable() const override { return !IsReceiver(); }
3363 };
3364
3365
3366 // Common base class for HArgumentsObject and HCapturedObject.
3367 class HDematerializedObject : public HInstruction {
3368 public:
3369 HDematerializedObject(int count, Zone* zone) : values_(count, zone) {}
3370
3371 int OperandCount() const final { return values_.length(); }
3372 HValue* OperandAt(int index) const final { return values_[index]; }
3373
3374 bool HasEscapingOperandAt(int index) final { return false; }
3375 Representation RequiredInputRepresentation(int index) final {
3376 return Representation::None();
3377 }
3378
3379 protected:
3380 void InternalSetOperandAt(int index, HValue* value) final {
3381 values_[index] = value;
3382 }
3383
3384 // List of values tracked by this marker.
3385 ZoneList<HValue*> values_;
3386 };
3387
3388
3389 class HArgumentsObject final : public HDematerializedObject {
3390 public:
3391 static HArgumentsObject* New(Isolate* isolate, Zone* zone, HValue* context,
3392 int count) {
3393 return new(zone) HArgumentsObject(count, zone);
3394 }
3395
3396 // The values contain a list of all elements in the arguments object
3397 // including the receiver object, which is skipped when materializing.
3398 const ZoneList<HValue*>* arguments_values() const { return &values_; }
3399 int arguments_count() const { return values_.length(); }
3400
3401 void AddArgument(HValue* argument, Zone* zone) {
3402 values_.Add(NULL, zone); // Resize list.
3403 SetOperandAt(values_.length() - 1, argument);
3404 }
3405
3406 DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
3407
3408 private:
3409 HArgumentsObject(int count, Zone* zone)
3410 : HDematerializedObject(count, zone) {
3411 set_representation(Representation::Tagged());
3412 SetFlag(kIsArguments);
3413 }
3414 };
3415
3416
3417 class HCapturedObject final : public HDematerializedObject {
3418 public:
3419 HCapturedObject(int length, int id, Zone* zone)
3420 : HDematerializedObject(length, zone), capture_id_(id) {
3421 set_representation(Representation::Tagged());
3422 values_.AddBlock(NULL, length, zone); // Resize list.
3423 }
3424
3425 // The values contain a list of all in-object properties inside the
3426 // captured object and is index by field index. Properties in the
3427 // properties or elements backing store are not tracked here.
3428 const ZoneList<HValue*>* values() const { return &values_; }
3429 int length() const { return values_.length(); }
3430 int capture_id() const { return capture_id_; }
3431
3432 // Shortcut for the map value of this captured object.
3433 HValue* map_value() const { return values()->first(); }
3434
3435 void ReuseSideEffectsFromStore(HInstruction* store) {
3436 DCHECK(store->HasObservableSideEffects());
3437 DCHECK(store->IsStoreNamedField());
3438 changes_flags_.Add(store->ChangesFlags());
3439 }
3440
3441 // Replay effects of this instruction on the given environment.
3442 void ReplayEnvironment(HEnvironment* env);
3443
3444 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
3445
3446 DECLARE_CONCRETE_INSTRUCTION(CapturedObject)
3447
3448 private:
3449 int capture_id_;
3450
3451 // Note that we cannot DCE captured objects as they are used to replay
3452 // the environment. This method is here as an explicit reminder.
3453 // TODO(mstarzinger): Turn HSimulates into full snapshots maybe?
3454 bool IsDeletable() const final { return false; }
3455 };
3456
3457
3458 class HConstant final : public HTemplateInstruction<0> {
3459 public:
3460 enum Special { kHoleNaN };
3461
3462 DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Special);
3463 DECLARE_INSTRUCTION_FACTORY_P1(HConstant, int32_t);
3464 DECLARE_INSTRUCTION_FACTORY_P2(HConstant, int32_t, Representation);
3465 DECLARE_INSTRUCTION_FACTORY_P1(HConstant, double);
3466 DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Handle<Object>);
3467 DECLARE_INSTRUCTION_FACTORY_P1(HConstant, ExternalReference);
3468
3469 static HConstant* CreateAndInsertAfter(Isolate* isolate, Zone* zone,
3470 HValue* context, int32_t value,
3471 Representation representation,
3472 HInstruction* instruction) {
3473 return instruction->Append(
3474 HConstant::New(isolate, zone, context, value, representation));
3475 }
3476
3477 Handle<Map> GetMonomorphicJSObjectMap() override {
3478 Handle<Object> object = object_.handle();
3479 if (!object.is_null() && object->IsHeapObject()) {
3480 return v8::internal::handle(HeapObject::cast(*object)->map());
3481 }
3482 return Handle<Map>();
3483 }
3484
3485 static HConstant* CreateAndInsertBefore(Isolate* isolate, Zone* zone,
3486 HValue* context, int32_t value,
3487 Representation representation,
3488 HInstruction* instruction) {
3489 return instruction->Prepend(
3490 HConstant::New(isolate, zone, context, value, representation));
3491 }
3492
3493 static HConstant* CreateAndInsertBefore(Zone* zone,
3494 Unique<Map> map,
3495 bool map_is_stable,
3496 HInstruction* instruction) {
3497 return instruction->Prepend(new(zone) HConstant(
3498 map, Unique<Map>(Handle<Map>::null()), map_is_stable,
3499 Representation::Tagged(), HType::HeapObject(), true,
3500 false, false, MAP_TYPE));
3501 }
3502
3503 static HConstant* CreateAndInsertAfter(Zone* zone,
3504 Unique<Map> map,
3505 bool map_is_stable,
3506 HInstruction* instruction) {
3507 return instruction->Append(new(zone) HConstant(
3508 map, Unique<Map>(Handle<Map>::null()), map_is_stable,
3509 Representation::Tagged(), HType::HeapObject(), true,
3510 false, false, MAP_TYPE));
3511 }
3512
3513 Handle<Object> handle(Isolate* isolate) {
3514 if (object_.handle().is_null()) {
3515 // Default arguments to is_not_in_new_space depend on this heap number
3516 // to be tenured so that it's guaranteed not to be located in new space.
3517 object_ = Unique<Object>::CreateUninitialized(
3518 isolate->factory()->NewNumber(double_value_, TENURED));
3519 }
3520 AllowDeferredHandleDereference smi_check;
3521 DCHECK(HasInteger32Value() || !object_.handle()->IsSmi());
3522 return object_.handle();
3523 }
3524
3525 bool IsSpecialDouble() const {
3526 return HasDoubleValue() &&
3527 (bit_cast<int64_t>(double_value_) == bit_cast<int64_t>(-0.0) ||
3528 std::isnan(double_value_));
3529 }
3530
3531 bool NotInNewSpace() const {
3532 return IsNotInNewSpaceField::decode(bit_field_);
3533 }
3534
3535 bool ImmortalImmovable() const;
3536
3537 bool IsCell() const {
3538 InstanceType instance_type = GetInstanceType();
3539 return instance_type == CELL_TYPE;
3540 }
3541
3542 Representation RequiredInputRepresentation(int index) override {
3543 return Representation::None();
3544 }
3545
3546 Representation KnownOptimalRepresentation() override {
3547 if (HasSmiValue() && SmiValuesAre31Bits()) return Representation::Smi();
3548 if (HasInteger32Value()) return Representation::Integer32();
3549 if (HasNumberValue()) return Representation::Double();
3550 if (HasExternalReferenceValue()) return Representation::External();
3551 return Representation::Tagged();
3552 }
3553
3554 bool EmitAtUses() override;
3555 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
3556 HConstant* CopyToRepresentation(Representation r, Zone* zone) const;
3557 Maybe<HConstant*> CopyToTruncatedInt32(Zone* zone);
3558 Maybe<HConstant*> CopyToTruncatedNumber(Isolate* isolate, Zone* zone);
3559 bool HasInteger32Value() const {
3560 return HasInt32ValueField::decode(bit_field_);
3561 }
3562 int32_t Integer32Value() const {
3563 DCHECK(HasInteger32Value());
3564 return int32_value_;
3565 }
3566 bool HasSmiValue() const { return HasSmiValueField::decode(bit_field_); }
3567 bool HasDoubleValue() const {
3568 return HasDoubleValueField::decode(bit_field_);
3569 }
3570 double DoubleValue() const {
3571 DCHECK(HasDoubleValue());
3572 return double_value_;
3573 }
3574 uint64_t DoubleValueAsBits() const {
3575 uint64_t bits;
3576 DCHECK(HasDoubleValue());
3577 STATIC_ASSERT(sizeof(bits) == sizeof(double_value_));
3578 std::memcpy(&bits, &double_value_, sizeof(bits));
3579 return bits;
3580 }
3581 bool IsTheHole() const {
3582 if (HasDoubleValue() && DoubleValueAsBits() == kHoleNanInt64) {
3583 return true;
3584 }
3585 return object_.IsInitialized() &&
3586 object_.IsKnownGlobal(isolate()->heap()->the_hole_value());
3587 }
3588 bool HasNumberValue() const { return HasDoubleValue(); }
3589 int32_t NumberValueAsInteger32() const {
3590 DCHECK(HasNumberValue());
3591 // Irrespective of whether a numeric HConstant can be safely
3592 // represented as an int32, we store the (in some cases lossy)
3593 // representation of the number in int32_value_.
3594 return int32_value_;
3595 }
3596 bool HasStringValue() const {
3597 if (HasNumberValue()) return false;
3598 DCHECK(!object_.handle().is_null());
3599 return GetInstanceType() < FIRST_NONSTRING_TYPE;
3600 }
3601 Handle<String> StringValue() const {
3602 DCHECK(HasStringValue());
3603 return Handle<String>::cast(object_.handle());
3604 }
3605 bool HasInternalizedStringValue() const {
3606 return HasStringValue() && StringShape(GetInstanceType()).IsInternalized();
3607 }
3608
3609 bool HasExternalReferenceValue() const {
3610 return HasExternalReferenceValueField::decode(bit_field_);
3611 }
3612 ExternalReference ExternalReferenceValue() const {
3613 return external_reference_value_;
3614 }
3615
3616 bool HasBooleanValue() const { return type_.IsBoolean(); }
3617 bool BooleanValue() const { return BooleanValueField::decode(bit_field_); }
3618 bool IsCallable() const { return IsCallableField::decode(bit_field_); }
3619 bool IsUndetectable() const {
3620 return IsUndetectableField::decode(bit_field_);
3621 }
3622 InstanceType GetInstanceType() const {
3623 return InstanceTypeField::decode(bit_field_);
3624 }
3625
3626 bool HasMapValue() const { return GetInstanceType() == MAP_TYPE; }
3627 Unique<Map> MapValue() const {
3628 DCHECK(HasMapValue());
3629 return Unique<Map>::cast(GetUnique());
3630 }
3631 bool HasStableMapValue() const {
3632 DCHECK(HasMapValue() || !HasStableMapValueField::decode(bit_field_));
3633 return HasStableMapValueField::decode(bit_field_);
3634 }
3635
3636 bool HasObjectMap() const { return !object_map_.IsNull(); }
3637 Unique<Map> ObjectMap() const {
3638 DCHECK(HasObjectMap());
3639 return object_map_;
3640 }
3641
3642 intptr_t Hashcode() override {
3643 if (HasInteger32Value()) {
3644 return static_cast<intptr_t>(int32_value_);
3645 } else if (HasDoubleValue()) {
3646 uint64_t bits = DoubleValueAsBits();
3647 if (sizeof(bits) > sizeof(intptr_t)) {
3648 bits ^= (bits >> 32);
3649 }
3650 return static_cast<intptr_t>(bits);
3651 } else if (HasExternalReferenceValue()) {
3652 return reinterpret_cast<intptr_t>(external_reference_value_.address());
3653 } else {
3654 DCHECK(!object_.handle().is_null());
3655 return object_.Hashcode();
3656 }
3657 }
3658
3659 void FinalizeUniqueness() override {
3660 if (!HasDoubleValue() && !HasExternalReferenceValue()) {
3661 DCHECK(!object_.handle().is_null());
3662 object_ = Unique<Object>(object_.handle());
3663 }
3664 }
3665
3666 Unique<Object> GetUnique() const {
3667 return object_;
3668 }
3669
3670 bool EqualsUnique(Unique<Object> other) const {
3671 return object_.IsInitialized() && object_ == other;
3672 }
3673
3674 bool DataEquals(HValue* other) override {
3675 HConstant* other_constant = HConstant::cast(other);
3676 if (HasInteger32Value()) {
3677 return other_constant->HasInteger32Value() &&
3678 int32_value_ == other_constant->int32_value_;
3679 } else if (HasDoubleValue()) {
3680 return other_constant->HasDoubleValue() &&
3681 std::memcmp(&double_value_, &other_constant->double_value_,
3682 sizeof(double_value_)) == 0;
3683 } else if (HasExternalReferenceValue()) {
3684 return other_constant->HasExternalReferenceValue() &&
3685 external_reference_value_ ==
3686 other_constant->external_reference_value_;
3687 } else {
3688 if (other_constant->HasInteger32Value() ||
3689 other_constant->HasDoubleValue() ||
3690 other_constant->HasExternalReferenceValue()) {
3691 return false;
3692 }
3693 DCHECK(!object_.handle().is_null());
3694 return other_constant->object_ == object_;
3695 }
3696 }
3697
3698 #ifdef DEBUG
3699 void Verify() override {}
3700 #endif
3701
3702 DECLARE_CONCRETE_INSTRUCTION(Constant)
3703
3704 protected:
3705 Range* InferRange(Zone* zone) override;
3706
3707 private:
3708 friend class HGraph;
3709 explicit HConstant(Special special);
3710 explicit HConstant(Handle<Object> handle,
3711 Representation r = Representation::None());
3712 HConstant(int32_t value,
3713 Representation r = Representation::None(),
3714 bool is_not_in_new_space = true,
3715 Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
3716 HConstant(double value,
3717 Representation r = Representation::None(),
3718 bool is_not_in_new_space = true,
3719 Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
3720 HConstant(Unique<Object> object,
3721 Unique<Map> object_map,
3722 bool has_stable_map_value,
3723 Representation r,
3724 HType type,
3725 bool is_not_in_new_space,
3726 bool boolean_value,
3727 bool is_undetectable,
3728 InstanceType instance_type);
3729
3730 explicit HConstant(ExternalReference reference);
3731
3732 void Initialize(Representation r);
3733
3734 bool IsDeletable() const override { return true; }
3735
3736 // If object_ is a map, this indicates whether the map is stable.
3737 class HasStableMapValueField : public BitField<bool, 0, 1> {};
3738
3739 // We store the HConstant in the most specific form safely possible.
3740 // These flags tell us if the respective member fields hold valid, safe
3741 // representations of the constant. More specific flags imply more general
3742 // flags, but not the converse (i.e. smi => int32 => double).
3743 class HasSmiValueField : public BitField<bool, 1, 1> {};
3744 class HasInt32ValueField : public BitField<bool, 2, 1> {};
3745 class HasDoubleValueField : public BitField<bool, 3, 1> {};
3746
3747 class HasExternalReferenceValueField : public BitField<bool, 4, 1> {};
3748 class IsNotInNewSpaceField : public BitField<bool, 5, 1> {};
3749 class BooleanValueField : public BitField<bool, 6, 1> {};
3750 class IsUndetectableField : public BitField<bool, 7, 1> {};
3751 class IsCallableField : public BitField<bool, 8, 1> {};
3752
3753 static const InstanceType kUnknownInstanceType = FILLER_TYPE;
3754 class InstanceTypeField : public BitField<InstanceType, 16, 8> {};
3755
3756 // If this is a numerical constant, object_ either points to the
3757 // HeapObject the constant originated from or is null. If the
3758 // constant is non-numeric, object_ always points to a valid
3759 // constant HeapObject.
3760 Unique<Object> object_;
3761
3762 // If object_ is a heap object, this points to the stable map of the object.
3763 Unique<Map> object_map_;
3764
3765 uint32_t bit_field_;
3766
3767 int32_t int32_value_;
3768 double double_value_;
3769 ExternalReference external_reference_value_;
3770 };
3771
3772
3773 class HBinaryOperation : public HTemplateInstruction<3> {
3774 public:
3775 HBinaryOperation(HValue* context, HValue* left, HValue* right,
3776 Strength strength, HType type = HType::Tagged())
3777 : HTemplateInstruction<3>(type),
3778 strength_(strength),
3779 observed_output_representation_(Representation::None()) {
3780 DCHECK(left != NULL && right != NULL);
3781 SetOperandAt(0, context);
3782 SetOperandAt(1, left);
3783 SetOperandAt(2, right);
3784 observed_input_representation_[0] = Representation::None();
3785 observed_input_representation_[1] = Representation::None();
3786 }
3787
3788 HValue* context() const { return OperandAt(0); }
3789 HValue* left() const { return OperandAt(1); }
3790 HValue* right() const { return OperandAt(2); }
3791 Strength strength() const { return strength_; }
3792
3793 // True if switching left and right operands likely generates better code.
3794 bool AreOperandsBetterSwitched() {
3795 if (!IsCommutative()) return false;
3796
3797 // Constant operands are better off on the right, they can be inlined in
3798 // many situations on most platforms.
3799 if (left()->IsConstant()) return true;
3800 if (right()->IsConstant()) return false;
3801
3802 // Otherwise, if there is only one use of the right operand, it would be
3803 // better off on the left for platforms that only have 2-arg arithmetic
3804 // ops (e.g ia32, x64) that clobber the left operand.
3805 return right()->HasOneUse();
3806 }
3807
3808 HValue* BetterLeftOperand() {
3809 return AreOperandsBetterSwitched() ? right() : left();
3810 }
3811
3812 HValue* BetterRightOperand() {
3813 return AreOperandsBetterSwitched() ? left() : right();
3814 }
3815
3816 void set_observed_input_representation(int index, Representation rep) {
3817 DCHECK(index >= 1 && index <= 2);
3818 observed_input_representation_[index - 1] = rep;
3819 }
3820
3821 virtual void initialize_output_representation(Representation observed) {
3822 observed_output_representation_ = observed;
3823 }
3824
3825 Representation observed_input_representation(int index) override {
3826 if (index == 0) return Representation::Tagged();
3827 return observed_input_representation_[index - 1];
3828 }
3829
3830 virtual void UpdateRepresentation(Representation new_rep,
3831 HInferRepresentationPhase* h_infer,
3832 const char* reason) override {
3833 Representation rep = !FLAG_smi_binop && new_rep.IsSmi()
3834 ? Representation::Integer32() : new_rep;
3835 HValue::UpdateRepresentation(rep, h_infer, reason);
3836 }
3837
3838 virtual void InferRepresentation(HInferRepresentationPhase* h_infer) override;
3839 Representation RepresentationFromInputs() override;
3840 Representation RepresentationFromOutput();
3841 void AssumeRepresentation(Representation r) override;
3842
3843 virtual bool IsCommutative() const { return false; }
3844
3845 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
3846
3847 Representation RequiredInputRepresentation(int index) override {
3848 if (index == 0) return Representation::Tagged();
3849 return representation();
3850 }
3851
3852 void SetOperandPositions(Zone* zone, SourcePosition left_pos,
3853 SourcePosition right_pos) {
3854 set_operand_position(zone, 1, left_pos);
3855 set_operand_position(zone, 2, right_pos);
3856 }
3857
3858 bool RightIsPowerOf2() {
3859 if (!right()->IsInteger32Constant()) return false;
3860 int32_t value = right()->GetInteger32Constant();
3861 if (value < 0) {
3862 return base::bits::IsPowerOfTwo32(static_cast<uint32_t>(-value));
3863 }
3864 return base::bits::IsPowerOfTwo32(static_cast<uint32_t>(value));
3865 }
3866
3867 Strength strength() { return strength_; }
3868
3869 DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation)
3870
3871 private:
3872 bool IgnoreObservedOutputRepresentation(Representation current_rep);
3873 Strength strength_;
3874
3875 Representation observed_input_representation_[2];
3876 Representation observed_output_representation_;
3877 };
3878
3879
3880 class HWrapReceiver final : public HTemplateInstruction<2> {
3881 public:
3882 DECLARE_INSTRUCTION_FACTORY_P2(HWrapReceiver, HValue*, HValue*);
3883
3884 bool DataEquals(HValue* other) override { return true; }
3885
3886 Representation RequiredInputRepresentation(int index) override {
3887 return Representation::Tagged();
3888 }
3889
3890 HValue* receiver() const { return OperandAt(0); }
3891 HValue* function() const { return OperandAt(1); }
3892
3893 HValue* Canonicalize() override;
3894
3895 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
3896 bool known_function() const { return known_function_; }
3897
3898 DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
3899
3900 private:
3901 HWrapReceiver(HValue* receiver, HValue* function) {
3902 known_function_ = function->IsConstant() &&
3903 HConstant::cast(function)->handle(function->isolate())->IsJSFunction();
3904 set_representation(Representation::Tagged());
3905 SetOperandAt(0, receiver);
3906 SetOperandAt(1, function);
3907 SetFlag(kUseGVN);
3908 }
3909
3910 bool known_function_;
3911 };
3912
3913
3914 class HApplyArguments final : public HTemplateInstruction<4> {
3915 public:
3916 DECLARE_INSTRUCTION_FACTORY_P4(HApplyArguments, HValue*, HValue*, HValue*,
3917 HValue*);
3918
3919 Representation RequiredInputRepresentation(int index) override {
3920 // The length is untagged, all other inputs are tagged.
3921 return (index == 2)
3922 ? Representation::Integer32()
3923 : Representation::Tagged();
3924 }
3925
3926 HValue* function() { return OperandAt(0); }
3927 HValue* receiver() { return OperandAt(1); }
3928 HValue* length() { return OperandAt(2); }
3929 HValue* elements() { return OperandAt(3); }
3930
3931 DECLARE_CONCRETE_INSTRUCTION(ApplyArguments)
3932
3933 private:
3934 HApplyArguments(HValue* function,
3935 HValue* receiver,
3936 HValue* length,
3937 HValue* elements) {
3938 set_representation(Representation::Tagged());
3939 SetOperandAt(0, function);
3940 SetOperandAt(1, receiver);
3941 SetOperandAt(2, length);
3942 SetOperandAt(3, elements);
3943 SetAllSideEffects();
3944 }
3945 };
3946
3947
3948 class HArgumentsElements final : public HTemplateInstruction<0> {
3949 public:
3950 DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsElements, bool);
3951
3952 DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
3953
3954 Representation RequiredInputRepresentation(int index) override {
3955 return Representation::None();
3956 }
3957
3958 bool from_inlined() const { return from_inlined_; }
3959
3960 protected:
3961 bool DataEquals(HValue* other) override { return true; }
3962
3963 private:
3964 explicit HArgumentsElements(bool from_inlined) : from_inlined_(from_inlined) {
3965 // The value produced by this instruction is a pointer into the stack
3966 // that looks as if it was a smi because of alignment.
3967 set_representation(Representation::Tagged());
3968 SetFlag(kUseGVN);
3969 }
3970
3971 bool IsDeletable() const override { return true; }
3972
3973 bool from_inlined_;
3974 };
3975
3976
3977 class HArgumentsLength final : public HUnaryOperation {
3978 public:
3979 DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsLength, HValue*);
3980
3981 Representation RequiredInputRepresentation(int index) override {
3982 return Representation::Tagged();
3983 }
3984
3985 DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)
3986
3987 protected:
3988 bool DataEquals(HValue* other) override { return true; }
3989
3990 private:
3991 explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
3992 set_representation(Representation::Integer32());
3993 SetFlag(kUseGVN);
3994 }
3995
3996 bool IsDeletable() const override { return true; }
3997 };
3998
3999
4000 class HAccessArgumentsAt final : public HTemplateInstruction<3> {
4001 public:
4002 DECLARE_INSTRUCTION_FACTORY_P3(HAccessArgumentsAt, HValue*, HValue*, HValue*);
4003
4004 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
4005
4006 Representation RequiredInputRepresentation(int index) override {
4007 // The arguments elements is considered tagged.
4008 return index == 0
4009 ? Representation::Tagged()
4010 : Representation::Integer32();
4011 }
4012
4013 HValue* arguments() const { return OperandAt(0); }
4014 HValue* length() const { return OperandAt(1); }
4015 HValue* index() const { return OperandAt(2); }
4016
4017 DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)
4018
4019 private:
4020 HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
4021 set_representation(Representation::Tagged());
4022 SetFlag(kUseGVN);
4023 SetOperandAt(0, arguments);
4024 SetOperandAt(1, length);
4025 SetOperandAt(2, index);
4026 }
4027
4028 bool DataEquals(HValue* other) override { return true; }
4029 };
4030
4031
4032 class HBoundsCheckBaseIndexInformation;
4033
4034
4035 class HBoundsCheck final : public HTemplateInstruction<2> {
4036 public:
4037 DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*);
4038
4039 bool skip_check() const { return skip_check_; }
4040 void set_skip_check() { skip_check_ = true; }
4041
4042 HValue* base() const { return base_; }
4043 int offset() const { return offset_; }
4044 int scale() const { return scale_; }
4045
4046 void ApplyIndexChange();
4047 bool DetectCompoundIndex() {
4048 DCHECK(base() == NULL);
4049
4050 DecompositionResult decomposition;
4051 if (index()->TryDecompose(&decomposition)) {
4052 base_ = decomposition.base();
4053 offset_ = decomposition.offset();
4054 scale_ = decomposition.scale();
4055 return true;
4056 } else {
4057 base_ = index();
4058 offset_ = 0;
4059 scale_ = 0;
4060 return false;
4061 }
4062 }
4063
4064 Representation RequiredInputRepresentation(int index) override {
4065 return representation();
4066 }
4067
4068 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
4069 virtual void InferRepresentation(HInferRepresentationPhase* h_infer) override;
4070
4071 HValue* index() const { return OperandAt(0); }
4072 HValue* length() const { return OperandAt(1); }
4073 bool allow_equality() const { return allow_equality_; }
4074 void set_allow_equality(bool v) { allow_equality_ = v; }
4075
4076 int RedefinedOperandIndex() override { return 0; }
4077 bool IsPurelyInformativeDefinition() override { return skip_check(); }
4078
4079 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
4080
4081 protected:
4082 friend class HBoundsCheckBaseIndexInformation;
4083
4084 Range* InferRange(Zone* zone) override;
4085
4086 bool DataEquals(HValue* other) override { return true; }
4087 bool skip_check_;
4088 HValue* base_;
4089 int offset_;
4090 int scale_;
4091 bool allow_equality_;
4092
4093 private:
4094 // Normally HBoundsCheck should be created using the
4095 // HGraphBuilder::AddBoundsCheck() helper.
4096 // However when building stubs, where we know that the arguments are Int32,
4097 // it makes sense to invoke this constructor directly.
4098 HBoundsCheck(HValue* index, HValue* length)
4099 : skip_check_(false),
4100 base_(NULL), offset_(0), scale_(0),
4101 allow_equality_(false) {
4102 SetOperandAt(0, index);
4103 SetOperandAt(1, length);
4104 SetFlag(kFlexibleRepresentation);
4105 SetFlag(kUseGVN);
4106 }
4107
4108 bool IsDeletable() const override { return skip_check() && !FLAG_debug_code; }
4109 };
4110
4111
4112 class HBoundsCheckBaseIndexInformation final : public HTemplateInstruction<2> {
4113 public:
4114 explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) {
4115 DecompositionResult decomposition;
4116 if (check->index()->TryDecompose(&decomposition)) {
4117 SetOperandAt(0, decomposition.base());
4118 SetOperandAt(1, check);
4119 } else {
4120 UNREACHABLE();
4121 }
4122 }
4123
4124 HValue* base_index() const { return OperandAt(0); }
4125 HBoundsCheck* bounds_check() { return HBoundsCheck::cast(OperandAt(1)); }
4126
4127 DECLARE_CONCRETE_INSTRUCTION(BoundsCheckBaseIndexInformation)
4128
4129 Representation RequiredInputRepresentation(int index) override {
4130 return representation();
4131 }
4132
4133 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
4134
4135 int RedefinedOperandIndex() override { return 0; }
4136 bool IsPurelyInformativeDefinition() override { return true; }
4137 };
4138
4139
4140 class HBitwiseBinaryOperation : public HBinaryOperation {
4141 public:
4142 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right,
4143 Strength strength, HType type = HType::TaggedNumber())
4144 : HBinaryOperation(context, left, right, strength, type) {
4145 SetFlag(kFlexibleRepresentation);
4146 SetFlag(kTruncatingToInt32);
4147 if (!is_strong(strength)) SetFlag(kAllowUndefinedAsNaN);
4148 SetAllSideEffects();
4149 }
4150
4151 void RepresentationChanged(Representation to) override {
4152 if (to.IsTagged() &&
4153 (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
4154 SetAllSideEffects();
4155 ClearFlag(kUseGVN);
4156 } else {
4157 ClearAllSideEffects();
4158 SetFlag(kUseGVN);
4159 }
4160 if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
4161 }
4162
4163 virtual void UpdateRepresentation(Representation new_rep,
4164 HInferRepresentationPhase* h_infer,
4165 const char* reason) override {
4166 // We only generate either int32 or generic tagged bitwise operations.
4167 if (new_rep.IsDouble()) new_rep = Representation::Integer32();
4168 HBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4169 }
4170
4171 Representation observed_input_representation(int index) override {
4172 Representation r = HBinaryOperation::observed_input_representation(index);
4173 if (r.IsDouble()) return Representation::Integer32();
4174 return r;
4175 }
4176
4177 virtual void initialize_output_representation(
4178 Representation observed) override {
4179 if (observed.IsDouble()) observed = Representation::Integer32();
4180 HBinaryOperation::initialize_output_representation(observed);
4181 }
4182
4183 DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
4184
4185 private:
4186 bool IsDeletable() const override { return true; }
4187 };
4188
4189
4190 class HMathFloorOfDiv final : public HBinaryOperation {
4191 public:
4192 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HMathFloorOfDiv,
4193 HValue*,
4194 HValue*);
4195
4196 DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv)
4197
4198 protected:
4199 bool DataEquals(HValue* other) override { return true; }
4200
4201 private:
4202 HMathFloorOfDiv(HValue* context, HValue* left, HValue* right)
4203 : HBinaryOperation(context, left, right, Strength::WEAK) {
4204 set_representation(Representation::Integer32());
4205 SetFlag(kUseGVN);
4206 SetFlag(kCanOverflow);
4207 SetFlag(kCanBeDivByZero);
4208 SetFlag(kLeftCanBeMinInt);
4209 SetFlag(kLeftCanBeNegative);
4210 SetFlag(kLeftCanBePositive);
4211 SetFlag(kAllowUndefinedAsNaN);
4212 }
4213
4214 Range* InferRange(Zone* zone) override;
4215
4216 bool IsDeletable() const override { return true; }
4217 };
4218
4219
4220 class HArithmeticBinaryOperation : public HBinaryOperation {
4221 public:
4222 HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right,
4223 Strength strength)
4224 : HBinaryOperation(context, left, right, strength,
4225 HType::TaggedNumber()) {
4226 SetAllSideEffects();
4227 SetFlag(kFlexibleRepresentation);
4228 if (!is_strong(strength)) SetFlag(kAllowUndefinedAsNaN);
4229 }
4230
4231 void RepresentationChanged(Representation to) override {
4232 if (to.IsTagged() &&
4233 (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
4234 SetAllSideEffects();
4235 ClearFlag(kUseGVN);
4236 } else {
4237 ClearAllSideEffects();
4238 SetFlag(kUseGVN);
4239 }
4240 if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
4241 }
4242
4243 DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)
4244
4245 private:
4246 bool IsDeletable() const override { return true; }
4247 };
4248
4249
4250 class HCompareGeneric final : public HBinaryOperation {
4251 public:
4252 static HCompareGeneric* New(Isolate* isolate, Zone* zone, HValue* context,
4253 HValue* left, HValue* right, Token::Value token,
4254 Strength strength = Strength::WEAK) {
4255 return new (zone) HCompareGeneric(context, left, right, token, strength);
4256 }
4257
4258 Representation RequiredInputRepresentation(int index) override {
4259 return index == 0
4260 ? Representation::Tagged()
4261 : representation();
4262 }
4263
4264 Token::Value token() const { return token_; }
4265 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
4266
4267 DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
4268
4269 private:
4270 HCompareGeneric(HValue* context, HValue* left, HValue* right,
4271 Token::Value token, Strength strength)
4272 : HBinaryOperation(context, left, right, strength, HType::Boolean()),
4273 token_(token) {
4274 DCHECK(Token::IsCompareOp(token));
4275 set_representation(Representation::Tagged());
4276 SetAllSideEffects();
4277 }
4278
4279 Token::Value token_;
4280 };
4281
4282
4283 class HCompareNumericAndBranch : public HTemplateControlInstruction<2, 2> {
4284 public:
4285 static HCompareNumericAndBranch* New(Isolate* isolate, Zone* zone,
4286 HValue* context, HValue* left,
4287 HValue* right, Token::Value token,
4288 HBasicBlock* true_target = NULL,
4289 HBasicBlock* false_target = NULL,
4290 Strength strength = Strength::WEAK) {
4291 return new (zone) HCompareNumericAndBranch(left, right, token, true_target,
4292 false_target, strength);
4293 }
4294 static HCompareNumericAndBranch* New(Isolate* isolate, Zone* zone,
4295 HValue* context, HValue* left,
4296 HValue* right, Token::Value token,
4297 Strength strength) {
4298 return new (zone)
4299 HCompareNumericAndBranch(left, right, token, NULL, NULL, strength);
4300 }
4301
4302 HValue* left() const { return OperandAt(0); }
4303 HValue* right() const { return OperandAt(1); }
4304 Token::Value token() const { return token_; }
4305
4306 void set_observed_input_representation(Representation left,
4307 Representation right) {
4308 observed_input_representation_[0] = left;
4309 observed_input_representation_[1] = right;
4310 }
4311
4312 virtual void InferRepresentation(HInferRepresentationPhase* h_infer) override;
4313
4314 Representation RequiredInputRepresentation(int index) override {
4315 return representation();
4316 }
4317 Representation observed_input_representation(int index) override {
4318 return observed_input_representation_[index];
4319 }
4320
4321 bool KnownSuccessorBlock(HBasicBlock** block) override;
4322
4323 Strength strength() const { return strength_; }
4324
4325 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
4326
4327 void SetOperandPositions(Zone* zone, SourcePosition left_pos,
4328 SourcePosition right_pos) {
4329 set_operand_position(zone, 0, left_pos);
4330 set_operand_position(zone, 1, right_pos);
4331 }
4332
4333 DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)
4334
4335 private:
4336 HCompareNumericAndBranch(HValue* left, HValue* right, Token::Value token,
4337 HBasicBlock* true_target, HBasicBlock* false_target,
4338 Strength strength)
4339 : token_(token), strength_(strength) {
4340 SetFlag(kFlexibleRepresentation);
4341 DCHECK(Token::IsCompareOp(token));
4342 SetOperandAt(0, left);
4343 SetOperandAt(1, right);
4344 SetSuccessorAt(0, true_target);
4345 SetSuccessorAt(1, false_target);
4346 }
4347
4348 Representation observed_input_representation_[2];
4349 Token::Value token_;
4350 Strength strength_;
4351 };
4352
4353
4354 class HCompareHoleAndBranch final : public HUnaryControlInstruction {
4355 public:
4356 DECLARE_INSTRUCTION_FACTORY_P1(HCompareHoleAndBranch, HValue*);
4357 DECLARE_INSTRUCTION_FACTORY_P3(HCompareHoleAndBranch, HValue*,
4358 HBasicBlock*, HBasicBlock*);
4359
4360 virtual void InferRepresentation(HInferRepresentationPhase* h_infer) override;
4361
4362 Representation RequiredInputRepresentation(int index) override {
4363 return representation();
4364 }
4365
4366 DECLARE_CONCRETE_INSTRUCTION(CompareHoleAndBranch)
4367
4368 private:
4369 HCompareHoleAndBranch(HValue* value,
4370 HBasicBlock* true_target = NULL,
4371 HBasicBlock* false_target = NULL)
4372 : HUnaryControlInstruction(value, true_target, false_target) {
4373 SetFlag(kFlexibleRepresentation);
4374 SetFlag(kAllowUndefinedAsNaN);
4375 }
4376 };
4377
4378
4379 class HCompareMinusZeroAndBranch final : public HUnaryControlInstruction {
4380 public:
4381 DECLARE_INSTRUCTION_FACTORY_P1(HCompareMinusZeroAndBranch, HValue*);
4382
4383 virtual void InferRepresentation(HInferRepresentationPhase* h_infer) override;
4384
4385 Representation RequiredInputRepresentation(int index) override {
4386 return representation();
4387 }
4388
4389 bool KnownSuccessorBlock(HBasicBlock** block) override;
4390
4391 DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch)
4392
4393 private:
4394 explicit HCompareMinusZeroAndBranch(HValue* value)
4395 : HUnaryControlInstruction(value, NULL, NULL) {
4396 }
4397 };
4398
4399
4400 class HCompareObjectEqAndBranch : public HTemplateControlInstruction<2, 2> {
4401 public:
4402 DECLARE_INSTRUCTION_FACTORY_P2(HCompareObjectEqAndBranch, HValue*, HValue*);
4403 DECLARE_INSTRUCTION_FACTORY_P4(HCompareObjectEqAndBranch, HValue*, HValue*,
4404 HBasicBlock*, HBasicBlock*);
4405
4406 bool KnownSuccessorBlock(HBasicBlock** block) override;
4407
4408 static const int kNoKnownSuccessorIndex = -1;
4409 int known_successor_index() const { return known_successor_index_; }
4410 void set_known_successor_index(int known_successor_index) {
4411 known_successor_index_ = known_successor_index;
4412 }
4413
4414 HValue* left() const { return OperandAt(0); }
4415 HValue* right() const { return OperandAt(1); }
4416
4417 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
4418
4419 Representation RequiredInputRepresentation(int index) override {
4420 return Representation::Tagged();
4421 }
4422
4423 Representation observed_input_representation(int index) override {
4424 return Representation::Tagged();
4425 }
4426
4427 DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)
4428
4429 private:
4430 HCompareObjectEqAndBranch(HValue* left,
4431 HValue* right,
4432 HBasicBlock* true_target = NULL,
4433 HBasicBlock* false_target = NULL)
4434 : known_successor_index_(kNoKnownSuccessorIndex) {
4435 SetOperandAt(0, left);
4436 SetOperandAt(1, right);
4437 SetSuccessorAt(0, true_target);
4438 SetSuccessorAt(1, false_target);
4439 }
4440
4441 int known_successor_index_;
4442 };
4443
4444
4445 class HIsStringAndBranch final : public HUnaryControlInstruction {
4446 public:
4447 DECLARE_INSTRUCTION_FACTORY_P1(HIsStringAndBranch, HValue*);
4448 DECLARE_INSTRUCTION_FACTORY_P3(HIsStringAndBranch, HValue*,
4449 HBasicBlock*, HBasicBlock*);
4450
4451 Representation RequiredInputRepresentation(int index) override {
4452 return Representation::Tagged();
4453 }
4454
4455 bool KnownSuccessorBlock(HBasicBlock** block) override;
4456
4457 static const int kNoKnownSuccessorIndex = -1;
4458 int known_successor_index() const { return known_successor_index_; }
4459 void set_known_successor_index(int known_successor_index) {
4460 known_successor_index_ = known_successor_index;
4461 }
4462
4463 DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
4464
4465 protected:
4466 int RedefinedOperandIndex() override { return 0; }
4467
4468 private:
4469 HIsStringAndBranch(HValue* value, HBasicBlock* true_target = NULL,
4470 HBasicBlock* false_target = NULL)
4471 : HUnaryControlInstruction(value, true_target, false_target),
4472 known_successor_index_(kNoKnownSuccessorIndex) {
4473 set_representation(Representation::Tagged());
4474 }
4475
4476 int known_successor_index_;
4477 };
4478
4479
4480 class HIsSmiAndBranch final : public HUnaryControlInstruction {
4481 public:
4482 DECLARE_INSTRUCTION_FACTORY_P1(HIsSmiAndBranch, HValue*);
4483 DECLARE_INSTRUCTION_FACTORY_P3(HIsSmiAndBranch, HValue*,
4484 HBasicBlock*, HBasicBlock*);
4485
4486 DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)
4487
4488 Representation RequiredInputRepresentation(int index) override {
4489 return Representation::Tagged();
4490 }
4491
4492 protected:
4493 bool DataEquals(HValue* other) override { return true; }
4494 int RedefinedOperandIndex() override { return 0; }
4495
4496 private:
4497 HIsSmiAndBranch(HValue* value,
4498 HBasicBlock* true_target = NULL,
4499 HBasicBlock* false_target = NULL)
4500 : HUnaryControlInstruction(value, true_target, false_target) {
4501 set_representation(Representation::Tagged());
4502 }
4503 };
4504
4505
4506 class HIsUndetectableAndBranch final : public HUnaryControlInstruction {
4507 public:
4508 DECLARE_INSTRUCTION_FACTORY_P1(HIsUndetectableAndBranch, HValue*);
4509 DECLARE_INSTRUCTION_FACTORY_P3(HIsUndetectableAndBranch, HValue*,
4510 HBasicBlock*, HBasicBlock*);
4511
4512 Representation RequiredInputRepresentation(int index) override {
4513 return Representation::Tagged();
4514 }
4515
4516 bool KnownSuccessorBlock(HBasicBlock** block) override;
4517
4518 DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)
4519
4520 private:
4521 HIsUndetectableAndBranch(HValue* value,
4522 HBasicBlock* true_target = NULL,
4523 HBasicBlock* false_target = NULL)
4524 : HUnaryControlInstruction(value, true_target, false_target) {}
4525 };
4526
4527
4528 class HStringCompareAndBranch final : public HTemplateControlInstruction<2, 3> {
4529 public:
4530 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HStringCompareAndBranch,
4531 HValue*,
4532 HValue*,
4533 Token::Value);
4534
4535 HValue* context() const { return OperandAt(0); }
4536 HValue* left() const { return OperandAt(1); }
4537 HValue* right() const { return OperandAt(2); }
4538 Token::Value token() const { return token_; }
4539
4540 std::ostream& PrintDataTo(std::ostream& os) const final; // NOLINT
4541
4542 Representation RequiredInputRepresentation(int index) final {
4543 return Representation::Tagged();
4544 }
4545
4546 DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)
4547
4548 private:
4549 HStringCompareAndBranch(HValue* context, HValue* left, HValue* right,
4550 Token::Value token)
4551 : token_(token) {
4552 DCHECK(Token::IsCompareOp(token));
4553 SetOperandAt(0, context);
4554 SetOperandAt(1, left);
4555 SetOperandAt(2, right);
4556 set_representation(Representation::Tagged());
4557 SetChangesFlag(kNewSpacePromotion);
4558 SetDependsOnFlag(kStringChars);
4559 SetDependsOnFlag(kStringLengths);
4560 }
4561
4562 Token::Value const token_;
4563 };
4564
4565
4566 class HIsConstructCallAndBranch : public HTemplateControlInstruction<2, 0> {
4567 public:
4568 DECLARE_INSTRUCTION_FACTORY_P0(HIsConstructCallAndBranch);
4569
4570 Representation RequiredInputRepresentation(int index) override {
4571 return Representation::None();
4572 }
4573
4574 DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch)
4575 private:
4576 HIsConstructCallAndBranch() {}
4577 };
4578
4579
4580 class HHasInstanceTypeAndBranch final : public HUnaryControlInstruction {
4581 public:
4582 DECLARE_INSTRUCTION_FACTORY_P2(
4583 HHasInstanceTypeAndBranch, HValue*, InstanceType);
4584 DECLARE_INSTRUCTION_FACTORY_P3(
4585 HHasInstanceTypeAndBranch, HValue*, InstanceType, InstanceType);
4586
4587 InstanceType from() { return from_; }
4588 InstanceType to() { return to_; }
4589
4590 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
4591
4592 Representation RequiredInputRepresentation(int index) override {
4593 return Representation::Tagged();
4594 }
4595
4596 bool KnownSuccessorBlock(HBasicBlock** block) override;
4597
4598 DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
4599
4600 private:
4601 HHasInstanceTypeAndBranch(HValue* value, InstanceType type)
4602 : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { }
4603 HHasInstanceTypeAndBranch(HValue* value, InstanceType from, InstanceType to)
4604 : HUnaryControlInstruction(value, NULL, NULL), from_(from), to_(to) {
4605 DCHECK(to == LAST_TYPE); // Others not implemented yet in backend.
4606 }
4607
4608 InstanceType from_;
4609 InstanceType to_; // Inclusive range, not all combinations work.
4610 };
4611
4612
4613 class HHasCachedArrayIndexAndBranch final : public HUnaryControlInstruction {
4614 public:
4615 DECLARE_INSTRUCTION_FACTORY_P1(HHasCachedArrayIndexAndBranch, HValue*);
4616
4617 Representation RequiredInputRepresentation(int index) override {
4618 return Representation::Tagged();
4619 }
4620
4621 DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch)
4622 private:
4623 explicit HHasCachedArrayIndexAndBranch(HValue* value)
4624 : HUnaryControlInstruction(value, NULL, NULL) { }
4625 };
4626
4627
4628 class HGetCachedArrayIndex final : public HUnaryOperation {
4629 public:
4630 DECLARE_INSTRUCTION_FACTORY_P1(HGetCachedArrayIndex, HValue*);
4631
4632 Representation RequiredInputRepresentation(int index) override {
4633 return Representation::Tagged();
4634 }
4635
4636 DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex)
4637
4638 protected:
4639 bool DataEquals(HValue* other) override { return true; }
4640
4641 private:
4642 explicit HGetCachedArrayIndex(HValue* value) : HUnaryOperation(value) {
4643 set_representation(Representation::Tagged());
4644 SetFlag(kUseGVN);
4645 }
4646
4647 bool IsDeletable() const override { return true; }
4648 };
4649
4650
4651 class HClassOfTestAndBranch final : public HUnaryControlInstruction {
4652 public:
4653 DECLARE_INSTRUCTION_FACTORY_P2(HClassOfTestAndBranch, HValue*,
4654 Handle<String>);
4655
4656 DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)
4657
4658 Representation RequiredInputRepresentation(int index) override {
4659 return Representation::Tagged();
4660 }
4661
4662 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
4663
4664 Handle<String> class_name() const { return class_name_; }
4665
4666 private:
4667 HClassOfTestAndBranch(HValue* value, Handle<String> class_name)
4668 : HUnaryControlInstruction(value, NULL, NULL),
4669 class_name_(class_name) { }
4670
4671 Handle<String> class_name_;
4672 };
4673
4674
4675 class HTypeofIsAndBranch final : public HUnaryControlInstruction {
4676 public:
4677 DECLARE_INSTRUCTION_FACTORY_P2(HTypeofIsAndBranch, HValue*, Handle<String>);
4678
4679 Handle<String> type_literal() const { return type_literal_.handle(); }
4680 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
4681
4682 DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
4683
4684 Representation RequiredInputRepresentation(int index) override {
4685 return Representation::None();
4686 }
4687
4688 bool KnownSuccessorBlock(HBasicBlock** block) override;
4689
4690 void FinalizeUniqueness() override {
4691 type_literal_ = Unique<String>(type_literal_.handle());
4692 }
4693
4694 private:
4695 HTypeofIsAndBranch(HValue* value, Handle<String> type_literal)
4696 : HUnaryControlInstruction(value, NULL, NULL),
4697 type_literal_(Unique<String>::CreateUninitialized(type_literal)) { }
4698
4699 Unique<String> type_literal_;
4700 };
4701
4702
4703 class HInstanceOf final : public HBinaryOperation {
4704 public:
4705 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInstanceOf, HValue*, HValue*);
4706
4707 Representation RequiredInputRepresentation(int index) override {
4708 return Representation::Tagged();
4709 }
4710
4711 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
4712
4713 DECLARE_CONCRETE_INSTRUCTION(InstanceOf)
4714
4715 private:
4716 HInstanceOf(HValue* context, HValue* left, HValue* right)
4717 : HBinaryOperation(context, left, right, Strength::WEAK,
4718 HType::Boolean()) {
4719 set_representation(Representation::Tagged());
4720 SetAllSideEffects();
4721 }
4722 };
4723
4724
4725 class HHasInPrototypeChainAndBranch final
4726 : public HTemplateControlInstruction<2, 2> {
4727 public:
4728 DECLARE_INSTRUCTION_FACTORY_P2(HHasInPrototypeChainAndBranch, HValue*,
4729 HValue*);
4730
4731 HValue* object() const { return OperandAt(0); }
4732 HValue* prototype() const { return OperandAt(1); }
4733
4734 Representation RequiredInputRepresentation(int index) override {
4735 return Representation::Tagged();
4736 }
4737
4738 bool ObjectNeedsSmiCheck() const {
4739 return !object()->type().IsHeapObject() &&
4740 !object()->representation().IsHeapObject();
4741 }
4742
4743 DECLARE_CONCRETE_INSTRUCTION(HasInPrototypeChainAndBranch)
4744
4745 private:
4746 HHasInPrototypeChainAndBranch(HValue* object, HValue* prototype) {
4747 SetOperandAt(0, object);
4748 SetOperandAt(1, prototype);
4749 SetDependsOnFlag(kCalls);
4750 }
4751 };
4752
4753
4754 class HPower final : public HTemplateInstruction<2> {
4755 public:
4756 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4757 HValue* left, HValue* right);
4758
4759 HValue* left() { return OperandAt(0); }
4760 HValue* right() const { return OperandAt(1); }
4761
4762 Representation RequiredInputRepresentation(int index) override {
4763 return index == 0
4764 ? Representation::Double()
4765 : Representation::None();
4766 }
4767 Representation observed_input_representation(int index) override {
4768 return RequiredInputRepresentation(index);
4769 }
4770
4771 DECLARE_CONCRETE_INSTRUCTION(Power)
4772
4773 protected:
4774 bool DataEquals(HValue* other) override { return true; }
4775
4776 private:
4777 HPower(HValue* left, HValue* right) {
4778 SetOperandAt(0, left);
4779 SetOperandAt(1, right);
4780 set_representation(Representation::Double());
4781 SetFlag(kUseGVN);
4782 SetChangesFlag(kNewSpacePromotion);
4783 }
4784
4785 bool IsDeletable() const override {
4786 return !right()->representation().IsTagged();
4787 }
4788 };
4789
4790
4791 enum ExternalAddType {
4792 AddOfExternalAndTagged,
4793 AddOfExternalAndInt32,
4794 NoExternalAdd
4795 };
4796
4797
4798 class HAdd final : public HArithmeticBinaryOperation {
4799 public:
4800 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4801 HValue* left, HValue* right,
4802 Strength strength = Strength::WEAK);
4803 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4804 HValue* left, HValue* right, Strength strength,
4805 ExternalAddType external_add_type);
4806
4807 // Add is only commutative if two integer values are added and not if two
4808 // tagged values are added (because it might be a String concatenation).
4809 // We also do not commute (pointer + offset).
4810 bool IsCommutative() const override {
4811 return !representation().IsTagged() && !representation().IsExternal();
4812 }
4813
4814 HValue* Canonicalize() override;
4815
4816 bool TryDecompose(DecompositionResult* decomposition) override {
4817 if (left()->IsInteger32Constant()) {
4818 decomposition->Apply(right(), left()->GetInteger32Constant());
4819 return true;
4820 } else if (right()->IsInteger32Constant()) {
4821 decomposition->Apply(left(), right()->GetInteger32Constant());
4822 return true;
4823 } else {
4824 return false;
4825 }
4826 }
4827
4828 void RepresentationChanged(Representation to) override {
4829 if (to.IsTagged() &&
4830 (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved() ||
4831 left()->ToStringCanBeObserved() || right()->ToStringCanBeObserved())) {
4832 SetAllSideEffects();
4833 ClearFlag(kUseGVN);
4834 } else {
4835 ClearAllSideEffects();
4836 SetFlag(kUseGVN);
4837 }
4838 if (to.IsTagged()) {
4839 SetChangesFlag(kNewSpacePromotion);
4840 ClearFlag(kAllowUndefinedAsNaN);
4841 }
4842 }
4843
4844 Representation RepresentationFromInputs() override;
4845
4846 Representation RequiredInputRepresentation(int index) override;
4847
4848 bool IsConsistentExternalRepresentation() {
4849 return left()->representation().IsExternal() &&
4850 ((external_add_type_ == AddOfExternalAndInt32 &&
4851 right()->representation().IsInteger32()) ||
4852 (external_add_type_ == AddOfExternalAndTagged &&
4853 right()->representation().IsTagged()));
4854 }
4855
4856 ExternalAddType external_add_type() const { return external_add_type_; }
4857
4858 DECLARE_CONCRETE_INSTRUCTION(Add)
4859
4860 protected:
4861 bool DataEquals(HValue* other) override { return true; }
4862
4863 Range* InferRange(Zone* zone) override;
4864
4865 private:
4866 HAdd(HValue* context, HValue* left, HValue* right, Strength strength,
4867 ExternalAddType external_add_type = NoExternalAdd)
4868 : HArithmeticBinaryOperation(context, left, right, strength),
4869 external_add_type_(external_add_type) {
4870 SetFlag(kCanOverflow);
4871 switch (external_add_type_) {
4872 case AddOfExternalAndTagged:
4873 DCHECK(left->representation().IsExternal());
4874 DCHECK(right->representation().IsTagged());
4875 SetDependsOnFlag(kNewSpacePromotion);
4876 ClearFlag(HValue::kCanOverflow);
4877 SetFlag(kHasNoObservableSideEffects);
4878 break;
4879
4880 case NoExternalAdd:
4881 // This is a bit of a hack: The call to this constructor is generated
4882 // by a macro that also supports sub and mul, so it doesn't pass in
4883 // a value for external_add_type but uses the default.
4884 if (left->representation().IsExternal()) {
4885 external_add_type_ = AddOfExternalAndInt32;
4886 }
4887 break;
4888
4889 case AddOfExternalAndInt32:
4890 // See comment above.
4891 UNREACHABLE();
4892 break;
4893 }
4894 }
4895
4896 ExternalAddType external_add_type_;
4897 };
4898
4899
4900 class HSub final : public HArithmeticBinaryOperation {
4901 public:
4902 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4903 HValue* left, HValue* right,
4904 Strength strength = Strength::WEAK);
4905
4906 HValue* Canonicalize() override;
4907
4908 bool TryDecompose(DecompositionResult* decomposition) override {
4909 if (right()->IsInteger32Constant()) {
4910 decomposition->Apply(left(), -right()->GetInteger32Constant());
4911 return true;
4912 } else {
4913 return false;
4914 }
4915 }
4916
4917 DECLARE_CONCRETE_INSTRUCTION(Sub)
4918
4919 protected:
4920 bool DataEquals(HValue* other) override { return true; }
4921
4922 Range* InferRange(Zone* zone) override;
4923
4924 private:
4925 HSub(HValue* context, HValue* left, HValue* right, Strength strength)
4926 : HArithmeticBinaryOperation(context, left, right, strength) {
4927 SetFlag(kCanOverflow);
4928 }
4929 };
4930
4931
4932 class HMul final : public HArithmeticBinaryOperation {
4933 public:
4934 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4935 HValue* left, HValue* right,
4936 Strength strength = Strength::WEAK);
4937
4938 static HInstruction* NewImul(Isolate* isolate, Zone* zone, HValue* context,
4939 HValue* left, HValue* right,
4940 Strength strength = Strength::WEAK) {
4941 HInstruction* instr =
4942 HMul::New(isolate, zone, context, left, right, strength);
4943 if (!instr->IsMul()) return instr;
4944 HMul* mul = HMul::cast(instr);
4945 // TODO(mstarzinger): Prevent bailout on minus zero for imul.
4946 mul->AssumeRepresentation(Representation::Integer32());
4947 mul->ClearFlag(HValue::kCanOverflow);
4948 return mul;
4949 }
4950
4951 HValue* Canonicalize() override;
4952
4953 // Only commutative if it is certain that not two objects are multiplicated.
4954 bool IsCommutative() const override { return !representation().IsTagged(); }
4955
4956 virtual void UpdateRepresentation(Representation new_rep,
4957 HInferRepresentationPhase* h_infer,
4958 const char* reason) override {
4959 HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4960 }
4961
4962 bool MulMinusOne();
4963
4964 DECLARE_CONCRETE_INSTRUCTION(Mul)
4965
4966 protected:
4967 bool DataEquals(HValue* other) override { return true; }
4968
4969 Range* InferRange(Zone* zone) override;
4970
4971 private:
4972 HMul(HValue* context, HValue* left, HValue* right, Strength strength)
4973 : HArithmeticBinaryOperation(context, left, right, strength) {
4974 SetFlag(kCanOverflow);
4975 }
4976 };
4977
4978
4979 class HMod final : public HArithmeticBinaryOperation {
4980 public:
4981 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4982 HValue* left, HValue* right,
4983 Strength strength = Strength::WEAK);
4984
4985 HValue* Canonicalize() override;
4986
4987 virtual void UpdateRepresentation(Representation new_rep,
4988 HInferRepresentationPhase* h_infer,
4989 const char* reason) override {
4990 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4991 HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4992 }
4993
4994 DECLARE_CONCRETE_INSTRUCTION(Mod)
4995
4996 protected:
4997 bool DataEquals(HValue* other) override { return true; }
4998
4999 Range* InferRange(Zone* zone) override;
5000
5001 private:
5002 HMod(HValue* context, HValue* left, HValue* right, Strength strength)
5003 : HArithmeticBinaryOperation(context, left, right, strength) {
5004 SetFlag(kCanBeDivByZero);
5005 SetFlag(kCanOverflow);
5006 SetFlag(kLeftCanBeNegative);
5007 }
5008 };
5009
5010
5011 class HDiv final : public HArithmeticBinaryOperation {
5012 public:
5013 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
5014 HValue* left, HValue* right,
5015 Strength strength = Strength::WEAK);
5016
5017 HValue* Canonicalize() override;
5018
5019 virtual void UpdateRepresentation(Representation new_rep,
5020 HInferRepresentationPhase* h_infer,
5021 const char* reason) override {
5022 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5023 HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5024 }
5025
5026 DECLARE_CONCRETE_INSTRUCTION(Div)
5027
5028 protected:
5029 bool DataEquals(HValue* other) override { return true; }
5030
5031 Range* InferRange(Zone* zone) override;
5032
5033 private:
5034 HDiv(HValue* context, HValue* left, HValue* right, Strength strength)
5035 : HArithmeticBinaryOperation(context, left, right, strength) {
5036 SetFlag(kCanBeDivByZero);
5037 SetFlag(kCanOverflow);
5038 }
5039 };
5040
5041
5042 class HMathMinMax final : public HArithmeticBinaryOperation {
5043 public:
5044 enum Operation { kMathMin, kMathMax };
5045
5046 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
5047 HValue* left, HValue* right, Operation op);
5048
5049 Representation observed_input_representation(int index) override {
5050 return RequiredInputRepresentation(index);
5051 }
5052
5053 virtual void InferRepresentation(HInferRepresentationPhase* h_infer) override;
5054
5055 Representation RepresentationFromInputs() override {
5056 Representation left_rep = left()->representation();
5057 Representation right_rep = right()->representation();
5058 Representation result = Representation::Smi();
5059 result = result.generalize(left_rep);
5060 result = result.generalize(right_rep);
5061 if (result.IsTagged()) return Representation::Double();
5062 return result;
5063 }
5064
5065 bool IsCommutative() const override { return true; }
5066
5067 Operation operation() { return operation_; }
5068
5069 DECLARE_CONCRETE_INSTRUCTION(MathMinMax)
5070
5071 protected:
5072 bool DataEquals(HValue* other) override {
5073 return other->IsMathMinMax() &&
5074 HMathMinMax::cast(other)->operation_ == operation_;
5075 }
5076
5077 Range* InferRange(Zone* zone) override;
5078
5079 private:
5080 HMathMinMax(HValue* context, HValue* left, HValue* right, Operation op)
5081 : HArithmeticBinaryOperation(context, left, right, Strength::WEAK),
5082 operation_(op) {}
5083
5084 Operation operation_;
5085 };
5086
5087
5088 class HBitwise final : public HBitwiseBinaryOperation {
5089 public:
5090 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
5091 Token::Value op, HValue* left, HValue* right,
5092 Strength strength = Strength::WEAK);
5093
5094 Token::Value op() const { return op_; }
5095
5096 bool IsCommutative() const override { return true; }
5097
5098 HValue* Canonicalize() override;
5099
5100 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
5101
5102 DECLARE_CONCRETE_INSTRUCTION(Bitwise)
5103
5104 protected:
5105 bool DataEquals(HValue* other) override {
5106 return op() == HBitwise::cast(other)->op();
5107 }
5108
5109 Range* InferRange(Zone* zone) override;
5110
5111 private:
5112 HBitwise(HValue* context, Token::Value op, HValue* left, HValue* right,
5113 Strength strength)
5114 : HBitwiseBinaryOperation(context, left, right, strength), op_(op) {
5115 DCHECK(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR);
5116 // BIT_AND with a smi-range positive value will always unset the
5117 // entire sign-extension of the smi-sign.
5118 if (op == Token::BIT_AND &&
5119 ((left->IsConstant() &&
5120 left->representation().IsSmi() &&
5121 HConstant::cast(left)->Integer32Value() >= 0) ||
5122 (right->IsConstant() &&
5123 right->representation().IsSmi() &&
5124 HConstant::cast(right)->Integer32Value() >= 0))) {
5125 SetFlag(kTruncatingToSmi);
5126 SetFlag(kTruncatingToInt32);
5127 // BIT_OR with a smi-range negative value will always set the entire
5128 // sign-extension of the smi-sign.
5129 } else if (op == Token::BIT_OR &&
5130 ((left->IsConstant() &&
5131 left->representation().IsSmi() &&
5132 HConstant::cast(left)->Integer32Value() < 0) ||
5133 (right->IsConstant() &&
5134 right->representation().IsSmi() &&
5135 HConstant::cast(right)->Integer32Value() < 0))) {
5136 SetFlag(kTruncatingToSmi);
5137 SetFlag(kTruncatingToInt32);
5138 }
5139 }
5140
5141 Token::Value op_;
5142 };
5143
5144
5145 class HShl final : public HBitwiseBinaryOperation {
5146 public:
5147 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
5148 HValue* left, HValue* right,
5149 Strength strength = Strength::WEAK);
5150
5151 Range* InferRange(Zone* zone) override;
5152
5153 virtual void UpdateRepresentation(Representation new_rep,
5154 HInferRepresentationPhase* h_infer,
5155 const char* reason) override {
5156 if (new_rep.IsSmi() &&
5157 !(right()->IsInteger32Constant() &&
5158 right()->GetInteger32Constant() >= 0)) {
5159 new_rep = Representation::Integer32();
5160 }
5161 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5162 }
5163
5164 DECLARE_CONCRETE_INSTRUCTION(Shl)
5165
5166 protected:
5167 bool DataEquals(HValue* other) override { return true; }
5168
5169 private:
5170 HShl(HValue* context, HValue* left, HValue* right, Strength strength)
5171 : HBitwiseBinaryOperation(context, left, right, strength) {}
5172 };
5173
5174
5175 class HShr final : public HBitwiseBinaryOperation {
5176 public:
5177 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
5178 HValue* left, HValue* right,
5179 Strength strength = Strength::WEAK);
5180
5181 bool TryDecompose(DecompositionResult* decomposition) override {
5182 if (right()->IsInteger32Constant()) {
5183 if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
5184 // This is intended to look for HAdd and HSub, to handle compounds
5185 // like ((base + offset) >> scale) with one single decomposition.
5186 left()->TryDecompose(decomposition);
5187 return true;
5188 }
5189 }
5190 return false;
5191 }
5192
5193 Range* InferRange(Zone* zone) override;
5194
5195 virtual void UpdateRepresentation(Representation new_rep,
5196 HInferRepresentationPhase* h_infer,
5197 const char* reason) override {
5198 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5199 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5200 }
5201
5202 DECLARE_CONCRETE_INSTRUCTION(Shr)
5203
5204 protected:
5205 bool DataEquals(HValue* other) override { return true; }
5206
5207 private:
5208 HShr(HValue* context, HValue* left, HValue* right, Strength strength)
5209 : HBitwiseBinaryOperation(context, left, right, strength) {}
5210 };
5211
5212
5213 class HSar final : public HBitwiseBinaryOperation {
5214 public:
5215 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
5216 HValue* left, HValue* right,
5217 Strength strength = Strength::WEAK);
5218
5219 bool TryDecompose(DecompositionResult* decomposition) override {
5220 if (right()->IsInteger32Constant()) {
5221 if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
5222 // This is intended to look for HAdd and HSub, to handle compounds
5223 // like ((base + offset) >> scale) with one single decomposition.
5224 left()->TryDecompose(decomposition);
5225 return true;
5226 }
5227 }
5228 return false;
5229 }
5230
5231 Range* InferRange(Zone* zone) override;
5232
5233 virtual void UpdateRepresentation(Representation new_rep,
5234 HInferRepresentationPhase* h_infer,
5235 const char* reason) override {
5236 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5237 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5238 }
5239
5240 DECLARE_CONCRETE_INSTRUCTION(Sar)
5241
5242 protected:
5243 bool DataEquals(HValue* other) override { return true; }
5244
5245 private:
5246 HSar(HValue* context, HValue* left, HValue* right, Strength strength)
5247 : HBitwiseBinaryOperation(context, left, right, strength) {}
5248 };
5249
5250
5251 class HRor final : public HBitwiseBinaryOperation {
5252 public:
5253 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
5254 HValue* left, HValue* right,
5255 Strength strength = Strength::WEAK) {
5256 return new (zone) HRor(context, left, right, strength);
5257 }
5258
5259 virtual void UpdateRepresentation(Representation new_rep,
5260 HInferRepresentationPhase* h_infer,
5261 const char* reason) override {
5262 if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5263 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5264 }
5265
5266 DECLARE_CONCRETE_INSTRUCTION(Ror)
5267
5268 protected:
5269 bool DataEquals(HValue* other) override { return true; }
5270
5271 private:
5272 HRor(HValue* context, HValue* left, HValue* right, Strength strength)
5273 : HBitwiseBinaryOperation(context, left, right, strength) {
5274 ChangeRepresentation(Representation::Integer32());
5275 }
5276 };
5277
5278
5279 class HOsrEntry final : public HTemplateInstruction<0> {
5280 public:
5281 DECLARE_INSTRUCTION_FACTORY_P1(HOsrEntry, BailoutId);
5282
5283 BailoutId ast_id() const { return ast_id_; }
5284
5285 Representation RequiredInputRepresentation(int index) override {
5286 return Representation::None();
5287 }
5288
5289 DECLARE_CONCRETE_INSTRUCTION(OsrEntry)
5290
5291 private:
5292 explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
5293 SetChangesFlag(kOsrEntries);
5294 SetChangesFlag(kNewSpacePromotion);
5295 }
5296
5297 BailoutId ast_id_;
5298 };
5299
5300
5301 class HParameter final : public HTemplateInstruction<0> {
5302 public:
5303 enum ParameterKind {
5304 STACK_PARAMETER,
5305 REGISTER_PARAMETER
5306 };
5307
5308 DECLARE_INSTRUCTION_FACTORY_P1(HParameter, unsigned);
5309 DECLARE_INSTRUCTION_FACTORY_P2(HParameter, unsigned, ParameterKind);
5310 DECLARE_INSTRUCTION_FACTORY_P3(HParameter, unsigned, ParameterKind,
5311 Representation);
5312
5313 unsigned index() const { return index_; }
5314 ParameterKind kind() const { return kind_; }
5315
5316 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
5317
5318 Representation RequiredInputRepresentation(int index) override {
5319 return Representation::None();
5320 }
5321
5322 Representation KnownOptimalRepresentation() override {
5323 // If a parameter is an input to a phi, that phi should not
5324 // choose any more optimistic representation than Tagged.
5325 return Representation::Tagged();
5326 }
5327
5328 DECLARE_CONCRETE_INSTRUCTION(Parameter)
5329
5330 private:
5331 explicit HParameter(unsigned index,
5332 ParameterKind kind = STACK_PARAMETER)
5333 : index_(index),
5334 kind_(kind) {
5335 set_representation(Representation::Tagged());
5336 }
5337
5338 explicit HParameter(unsigned index,
5339 ParameterKind kind,
5340 Representation r)
5341 : index_(index),
5342 kind_(kind) {
5343 set_representation(r);
5344 }
5345
5346 unsigned index_;
5347 ParameterKind kind_;
5348 };
5349
5350
5351 class HCallStub final : public HUnaryCall {
5352 public:
5353 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallStub, CodeStub::Major, int);
5354 CodeStub::Major major_key() { return major_key_; }
5355
5356 HValue* context() { return value(); }
5357
5358 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
5359
5360 DECLARE_CONCRETE_INSTRUCTION(CallStub)
5361
5362 private:
5363 HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
5364 : HUnaryCall(context, argument_count),
5365 major_key_(major_key) {
5366 }
5367
5368 CodeStub::Major major_key_;
5369 };
5370
5371
5372 class HUnknownOSRValue final : public HTemplateInstruction<0> {
5373 public:
5374 DECLARE_INSTRUCTION_FACTORY_P2(HUnknownOSRValue, HEnvironment*, int);
5375
5376 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
5377
5378 Representation RequiredInputRepresentation(int index) override {
5379 return Representation::None();
5380 }
5381
5382 void set_incoming_value(HPhi* value) { incoming_value_ = value; }
5383 HPhi* incoming_value() { return incoming_value_; }
5384 HEnvironment *environment() { return environment_; }
5385 int index() { return index_; }
5386
5387 Representation KnownOptimalRepresentation() override {
5388 if (incoming_value_ == NULL) return Representation::None();
5389 return incoming_value_->KnownOptimalRepresentation();
5390 }
5391
5392 DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
5393
5394 private:
5395 HUnknownOSRValue(HEnvironment* environment, int index)
5396 : environment_(environment),
5397 index_(index),
5398 incoming_value_(NULL) {
5399 set_representation(Representation::Tagged());
5400 }
5401
5402 HEnvironment* environment_;
5403 int index_;
5404 HPhi* incoming_value_;
5405 };
5406
5407
5408 class HLoadGlobalGeneric final : public HTemplateInstruction<2> {
5409 public:
5410 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HLoadGlobalGeneric, HValue*,
5411 Handle<String>, TypeofMode);
5412
5413 HValue* context() { return OperandAt(0); }
5414 HValue* global_object() { return OperandAt(1); }
5415 Handle<String> name() const { return name_; }
5416 TypeofMode typeof_mode() const { return typeof_mode_; }
5417 FeedbackVectorSlot slot() const { return slot_; }
5418 Handle<TypeFeedbackVector> feedback_vector() const {
5419 return feedback_vector_;
5420 }
5421 bool HasVectorAndSlot() const { return true; }
5422 void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
5423 FeedbackVectorSlot slot) {
5424 feedback_vector_ = vector;
5425 slot_ = slot;
5426 }
5427
5428 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
5429
5430 Representation RequiredInputRepresentation(int index) override {
5431 return Representation::Tagged();
5432 }
5433
5434 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric)
5435
5436 private:
5437 HLoadGlobalGeneric(HValue* context, HValue* global_object,
5438 Handle<String> name, TypeofMode typeof_mode)
5439 : name_(name), typeof_mode_(typeof_mode) {
5440 SetOperandAt(0, context);
5441 SetOperandAt(1, global_object);
5442 set_representation(Representation::Tagged());
5443 SetAllSideEffects();
5444 }
5445
5446 Handle<String> name_;
5447 TypeofMode typeof_mode_;
5448 Handle<TypeFeedbackVector> feedback_vector_;
5449 FeedbackVectorSlot slot_;
5450 };
5451
5452
5453 class HLoadGlobalViaContext final : public HTemplateInstruction<1> {
5454 public:
5455 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HLoadGlobalViaContext, int, int);
5456
5457 HValue* context() { return OperandAt(0); }
5458 int depth() const { return depth_; }
5459 int slot_index() const { return slot_index_; }
5460
5461 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
5462
5463 Representation RequiredInputRepresentation(int index) override {
5464 return Representation::Tagged();
5465 }
5466
5467 DECLARE_CONCRETE_INSTRUCTION(LoadGlobalViaContext)
5468
5469 private:
5470 HLoadGlobalViaContext(HValue* context, int depth, int slot_index)
5471 : depth_(depth), slot_index_(slot_index) {
5472 SetOperandAt(0, context);
5473 set_representation(Representation::Tagged());
5474 SetAllSideEffects();
5475 }
5476
5477 int const depth_;
5478 int const slot_index_;
5479 };
5480
5481
5482 class HAllocate final : public HTemplateInstruction<2> {
5483 public:
5484 static bool CompatibleInstanceTypes(InstanceType type1,
5485 InstanceType type2) {
5486 return ComputeFlags(TENURED, type1) == ComputeFlags(TENURED, type2) &&
5487 ComputeFlags(NOT_TENURED, type1) == ComputeFlags(NOT_TENURED, type2);
5488 }
5489
5490 static HAllocate* New(
5491 Isolate* isolate, Zone* zone, HValue* context, HValue* size, HType type,
5492 PretenureFlag pretenure_flag, InstanceType instance_type,
5493 Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null()) {
5494 return new(zone) HAllocate(context, size, type, pretenure_flag,
5495 instance_type, allocation_site);
5496 }
5497
5498 // Maximum instance size for which allocations will be inlined.
5499 static const int kMaxInlineSize = 64 * kPointerSize;
5500
5501 HValue* context() const { return OperandAt(0); }
5502 HValue* size() const { return OperandAt(1); }
5503
5504 bool has_size_upper_bound() { return size_upper_bound_ != NULL; }
5505 HConstant* size_upper_bound() { return size_upper_bound_; }
5506 void set_size_upper_bound(HConstant* value) {
5507 DCHECK(size_upper_bound_ == NULL);
5508 size_upper_bound_ = value;
5509 }
5510
5511 Representation RequiredInputRepresentation(int index) override {
5512 if (index == 0) {
5513 return Representation::Tagged();
5514 } else {
5515 return Representation::Integer32();
5516 }
5517 }
5518
5519 Handle<Map> GetMonomorphicJSObjectMap() override {
5520 return known_initial_map_;
5521 }
5522
5523 void set_known_initial_map(Handle<Map> known_initial_map) {
5524 known_initial_map_ = known_initial_map;
5525 }
5526
5527 bool IsNewSpaceAllocation() const {
5528 return (flags_ & ALLOCATE_IN_NEW_SPACE) != 0;
5529 }
5530
5531 bool IsOldSpaceAllocation() const {
5532 return (flags_ & ALLOCATE_IN_OLD_SPACE) != 0;
5533 }
5534
5535 bool MustAllocateDoubleAligned() const {
5536 return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0;
5537 }
5538
5539 bool MustPrefillWithFiller() const {
5540 return (flags_ & PREFILL_WITH_FILLER) != 0;
5541 }
5542
5543 void MakePrefillWithFiller() {
5544 flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER);
5545 }
5546
5547 bool MustClearNextMapWord() const {
5548 return (flags_ & CLEAR_NEXT_MAP_WORD) != 0;
5549 }
5550
5551 void MakeDoubleAligned() {
5552 flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED);
5553 }
5554
5555 virtual bool HandleSideEffectDominator(GVNFlag side_effect,
5556 HValue* dominator) override;
5557
5558 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
5559
5560 DECLARE_CONCRETE_INSTRUCTION(Allocate)
5561
5562 private:
5563 enum Flags {
5564 ALLOCATE_IN_NEW_SPACE = 1 << 0,
5565 ALLOCATE_IN_OLD_SPACE = 1 << 2,
5566 ALLOCATE_DOUBLE_ALIGNED = 1 << 3,
5567 PREFILL_WITH_FILLER = 1 << 4,
5568 CLEAR_NEXT_MAP_WORD = 1 << 5
5569 };
5570
5571 HAllocate(HValue* context,
5572 HValue* size,
5573 HType type,
5574 PretenureFlag pretenure_flag,
5575 InstanceType instance_type,
5576 Handle<AllocationSite> allocation_site =
5577 Handle<AllocationSite>::null())
5578 : HTemplateInstruction<2>(type),
5579 flags_(ComputeFlags(pretenure_flag, instance_type)),
5580 dominating_allocate_(NULL),
5581 filler_free_space_size_(NULL),
5582 size_upper_bound_(NULL) {
5583 SetOperandAt(0, context);
5584 UpdateSize(size);
5585 set_representation(Representation::Tagged());
5586 SetFlag(kTrackSideEffectDominators);
5587 SetChangesFlag(kNewSpacePromotion);
5588 SetDependsOnFlag(kNewSpacePromotion);
5589
5590 if (FLAG_trace_pretenuring) {
5591 PrintF("HAllocate with AllocationSite %p %s\n",
5592 allocation_site.is_null()
5593 ? static_cast<void*>(NULL)
5594 : static_cast<void*>(*allocation_site),
5595 pretenure_flag == TENURED ? "tenured" : "not tenured");
5596 }
5597 }
5598
5599 static Flags ComputeFlags(PretenureFlag pretenure_flag,
5600 InstanceType instance_type) {
5601 Flags flags = pretenure_flag == TENURED ? ALLOCATE_IN_OLD_SPACE
5602 : ALLOCATE_IN_NEW_SPACE;
5603 if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
5604 flags = static_cast<Flags>(flags | ALLOCATE_DOUBLE_ALIGNED);
5605 }
5606 // We have to fill the allocated object with one word fillers if we do
5607 // not use allocation folding since some allocations may depend on each
5608 // other, i.e., have a pointer to each other. A GC in between these
5609 // allocations may leave such objects behind in a not completely initialized
5610 // state.
5611 if (!FLAG_use_gvn || !FLAG_use_allocation_folding) {
5612 flags = static_cast<Flags>(flags | PREFILL_WITH_FILLER);
5613 }
5614 if (pretenure_flag == NOT_TENURED &&
5615 AllocationSite::CanTrack(instance_type)) {
5616 flags = static_cast<Flags>(flags | CLEAR_NEXT_MAP_WORD);
5617 }
5618 return flags;
5619 }
5620
5621 void UpdateClearNextMapWord(bool clear_next_map_word) {
5622 flags_ = static_cast<Flags>(clear_next_map_word
5623 ? flags_ | CLEAR_NEXT_MAP_WORD
5624 : flags_ & ~CLEAR_NEXT_MAP_WORD);
5625 }
5626
5627 void UpdateSize(HValue* size) {
5628 SetOperandAt(1, size);
5629 if (size->IsInteger32Constant()) {
5630 size_upper_bound_ = HConstant::cast(size);
5631 } else {
5632 size_upper_bound_ = NULL;
5633 }
5634 }
5635
5636 HAllocate* GetFoldableDominator(HAllocate* dominator);
5637
5638 void UpdateFreeSpaceFiller(int32_t filler_size);
5639
5640 void CreateFreeSpaceFiller(int32_t filler_size);
5641
5642 bool IsFoldable(HAllocate* allocate) {
5643 return (IsNewSpaceAllocation() && allocate->IsNewSpaceAllocation()) ||
5644 (IsOldSpaceAllocation() && allocate->IsOldSpaceAllocation());
5645 }
5646
5647 void ClearNextMapWord(int offset);
5648
5649 Flags flags_;
5650 Handle<Map> known_initial_map_;
5651 HAllocate* dominating_allocate_;
5652 HStoreNamedField* filler_free_space_size_;
5653 HConstant* size_upper_bound_;
5654 };
5655
5656
5657 class HStoreCodeEntry final : public HTemplateInstruction<2> {
5658 public:
5659 static HStoreCodeEntry* New(Isolate* isolate, Zone* zone, HValue* context,
5660 HValue* function, HValue* code) {
5661 return new(zone) HStoreCodeEntry(function, code);
5662 }
5663
5664 Representation RequiredInputRepresentation(int index) override {
5665 return Representation::Tagged();
5666 }
5667
5668 HValue* function() { return OperandAt(0); }
5669 HValue* code_object() { return OperandAt(1); }
5670
5671 DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry)
5672
5673 private:
5674 HStoreCodeEntry(HValue* function, HValue* code) {
5675 SetOperandAt(0, function);
5676 SetOperandAt(1, code);
5677 }
5678 };
5679
5680
5681 class HInnerAllocatedObject final : public HTemplateInstruction<2> {
5682 public:
5683 static HInnerAllocatedObject* New(Isolate* isolate, Zone* zone,
5684 HValue* context, HValue* value,
5685 HValue* offset, HType type) {
5686 return new(zone) HInnerAllocatedObject(value, offset, type);
5687 }
5688
5689 HValue* base_object() const { return OperandAt(0); }
5690 HValue* offset() const { return OperandAt(1); }
5691
5692 Representation RequiredInputRepresentation(int index) override {
5693 return index == 0 ? Representation::Tagged() : Representation::Integer32();
5694 }
5695
5696 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
5697
5698 DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject)
5699
5700 private:
5701 HInnerAllocatedObject(HValue* value,
5702 HValue* offset,
5703 HType type) : HTemplateInstruction<2>(type) {
5704 DCHECK(value->IsAllocate());
5705 DCHECK(type.IsHeapObject());
5706 SetOperandAt(0, value);
5707 SetOperandAt(1, offset);
5708 set_representation(Representation::Tagged());
5709 }
5710 };
5711
5712
5713 inline bool StoringValueNeedsWriteBarrier(HValue* value) {
5714 return !value->type().IsSmi()
5715 && !value->type().IsNull()
5716 && !value->type().IsBoolean()
5717 && !value->type().IsUndefined()
5718 && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable());
5719 }
5720
5721
5722 inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
5723 HValue* value,
5724 HValue* dominator) {
5725 while (object->IsInnerAllocatedObject()) {
5726 object = HInnerAllocatedObject::cast(object)->base_object();
5727 }
5728 if (object->IsConstant() &&
5729 HConstant::cast(object)->HasExternalReferenceValue()) {
5730 // Stores to external references require no write barriers
5731 return false;
5732 }
5733 // We definitely need a write barrier unless the object is the allocation
5734 // dominator.
5735 if (object == dominator && object->IsAllocate()) {
5736 // Stores to new space allocations require no write barriers.
5737 if (HAllocate::cast(object)->IsNewSpaceAllocation()) {
5738 return false;
5739 }
5740 // Stores to old space allocations require no write barriers if the value is
5741 // a constant provably not in new space.
5742 if (value->IsConstant() && HConstant::cast(value)->NotInNewSpace()) {
5743 return false;
5744 }
5745 // Stores to old space allocations require no write barriers if the value is
5746 // an old space allocation.
5747 while (value->IsInnerAllocatedObject()) {
5748 value = HInnerAllocatedObject::cast(value)->base_object();
5749 }
5750 if (value->IsAllocate() &&
5751 !HAllocate::cast(value)->IsNewSpaceAllocation()) {
5752 return false;
5753 }
5754 }
5755 return true;
5756 }
5757
5758
5759 inline PointersToHereCheck PointersToHereCheckForObject(HValue* object,
5760 HValue* dominator) {
5761 while (object->IsInnerAllocatedObject()) {
5762 object = HInnerAllocatedObject::cast(object)->base_object();
5763 }
5764 if (object == dominator &&
5765 object->IsAllocate() &&
5766 HAllocate::cast(object)->IsNewSpaceAllocation()) {
5767 return kPointersToHereAreAlwaysInteresting;
5768 }
5769 return kPointersToHereMaybeInteresting;
5770 }
5771
5772
5773 class HLoadContextSlot final : public HUnaryOperation {
5774 public:
5775 enum Mode {
5776 // Perform a normal load of the context slot without checking its value.
5777 kNoCheck,
5778 // Load and check the value of the context slot. Deoptimize if it's the
5779 // hole value. This is used for checking for loading of uninitialized
5780 // harmony bindings where we deoptimize into full-codegen generated code
5781 // which will subsequently throw a reference error.
5782 kCheckDeoptimize,
5783 // Load and check the value of the context slot. Return undefined if it's
5784 // the hole value. This is used for non-harmony const assignments
5785 kCheckReturnUndefined
5786 };
5787
5788 HLoadContextSlot(HValue* context, int slot_index, Mode mode)
5789 : HUnaryOperation(context), slot_index_(slot_index), mode_(mode) {
5790 set_representation(Representation::Tagged());
5791 SetFlag(kUseGVN);
5792 SetDependsOnFlag(kContextSlots);
5793 }
5794
5795 int slot_index() const { return slot_index_; }
5796 Mode mode() const { return mode_; }
5797
5798 bool DeoptimizesOnHole() {
5799 return mode_ == kCheckDeoptimize;
5800 }
5801
5802 bool RequiresHoleCheck() const {
5803 return mode_ != kNoCheck;
5804 }
5805
5806 Representation RequiredInputRepresentation(int index) override {
5807 return Representation::Tagged();
5808 }
5809
5810 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
5811
5812 DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)
5813
5814 protected:
5815 bool DataEquals(HValue* other) override {
5816 HLoadContextSlot* b = HLoadContextSlot::cast(other);
5817 return (slot_index() == b->slot_index());
5818 }
5819
5820 private:
5821 bool IsDeletable() const override { return !RequiresHoleCheck(); }
5822
5823 int slot_index_;
5824 Mode mode_;
5825 };
5826
5827
5828 class HStoreContextSlot final : public HTemplateInstruction<2> {
5829 public:
5830 enum Mode {
5831 // Perform a normal store to the context slot without checking its previous
5832 // value.
5833 kNoCheck,
5834 // Check the previous value of the context slot and deoptimize if it's the
5835 // hole value. This is used for checking for assignments to uninitialized
5836 // harmony bindings where we deoptimize into full-codegen generated code
5837 // which will subsequently throw a reference error.
5838 kCheckDeoptimize,
5839 // Check the previous value and ignore assignment if it isn't a hole value
5840 kCheckIgnoreAssignment
5841 };
5842
5843 DECLARE_INSTRUCTION_FACTORY_P4(HStoreContextSlot, HValue*, int,
5844 Mode, HValue*);
5845
5846 HValue* context() const { return OperandAt(0); }
5847 HValue* value() const { return OperandAt(1); }
5848 int slot_index() const { return slot_index_; }
5849 Mode mode() const { return mode_; }
5850
5851 bool NeedsWriteBarrier() {
5852 return StoringValueNeedsWriteBarrier(value());
5853 }
5854
5855 bool DeoptimizesOnHole() {
5856 return mode_ == kCheckDeoptimize;
5857 }
5858
5859 bool RequiresHoleCheck() {
5860 return mode_ != kNoCheck;
5861 }
5862
5863 Representation RequiredInputRepresentation(int index) override {
5864 return Representation::Tagged();
5865 }
5866
5867 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
5868
5869 DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
5870
5871 private:
5872 HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
5873 : slot_index_(slot_index), mode_(mode) {
5874 SetOperandAt(0, context);
5875 SetOperandAt(1, value);
5876 SetChangesFlag(kContextSlots);
5877 }
5878
5879 int slot_index_;
5880 Mode mode_;
5881 };
5882
5883
5884 // Represents an access to a portion of an object, such as the map pointer,
5885 // array elements pointer, etc, but not accesses to array elements themselves.
5886 class HObjectAccess final {
5887 public:
5888 inline bool IsInobject() const {
5889 return portion() != kBackingStore && portion() != kExternalMemory;
5890 }
5891
5892 inline bool IsExternalMemory() const {
5893 return portion() == kExternalMemory;
5894 }
5895
5896 inline bool IsStringLength() const {
5897 return portion() == kStringLengths;
5898 }
5899
5900 inline bool IsMap() const {
5901 return portion() == kMaps;
5902 }
5903
5904 inline int offset() const {
5905 return OffsetField::decode(value_);
5906 }
5907
5908 inline Representation representation() const {
5909 return Representation::FromKind(RepresentationField::decode(value_));
5910 }
5911
5912 inline Handle<Name> name() const { return name_; }
5913
5914 inline bool immutable() const {
5915 return ImmutableField::decode(value_);
5916 }
5917
5918 // Returns true if access is being made to an in-object property that
5919 // was already added to the object.
5920 inline bool existing_inobject_property() const {
5921 return ExistingInobjectPropertyField::decode(value_);
5922 }
5923
5924 inline HObjectAccess WithRepresentation(Representation representation) {
5925 return HObjectAccess(portion(), offset(), representation, name(),
5926 immutable(), existing_inobject_property());
5927 }
5928
5929 static HObjectAccess ForHeapNumberValue() {
5930 return HObjectAccess(
5931 kDouble, HeapNumber::kValueOffset, Representation::Double());
5932 }
5933
5934 static HObjectAccess ForHeapNumberValueLowestBits() {
5935 return HObjectAccess(kDouble,
5936 HeapNumber::kValueOffset,
5937 Representation::Integer32());
5938 }
5939
5940 static HObjectAccess ForHeapNumberValueHighestBits() {
5941 return HObjectAccess(kDouble,
5942 HeapNumber::kValueOffset + kIntSize,
5943 Representation::Integer32());
5944 }
5945
5946 static HObjectAccess ForOddballToNumber(
5947 Representation representation = Representation::Tagged()) {
5948 return HObjectAccess(kInobject, Oddball::kToNumberOffset, representation);
5949 }
5950
5951 static HObjectAccess ForOddballTypeOf() {
5952 return HObjectAccess(kInobject, Oddball::kTypeOfOffset,
5953 Representation::HeapObject());
5954 }
5955
5956 static HObjectAccess ForElementsPointer() {
5957 return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
5958 }
5959
5960 static HObjectAccess ForLiteralsPointer() {
5961 return HObjectAccess(kInobject, JSFunction::kLiteralsOffset);
5962 }
5963
5964 static HObjectAccess ForNextFunctionLinkPointer() {
5965 return HObjectAccess(kInobject, JSFunction::kNextFunctionLinkOffset);
5966 }
5967
5968 static HObjectAccess ForArrayLength(ElementsKind elements_kind) {
5969 return HObjectAccess(
5970 kArrayLengths,
5971 JSArray::kLengthOffset,
5972 IsFastElementsKind(elements_kind)
5973 ? Representation::Smi() : Representation::Tagged());
5974 }
5975
5976 static HObjectAccess ForAllocationSiteOffset(int offset);
5977
5978 static HObjectAccess ForAllocationSiteList() {
5979 return HObjectAccess(kExternalMemory, 0, Representation::Tagged(),
5980 Handle<Name>::null(), false, false);
5981 }
5982
5983 static HObjectAccess ForFixedArrayLength() {
5984 return HObjectAccess(
5985 kArrayLengths,
5986 FixedArray::kLengthOffset,
5987 Representation::Smi());
5988 }
5989
5990 static HObjectAccess ForFixedTypedArrayBaseBasePointer() {
5991 return HObjectAccess(kInobject, FixedTypedArrayBase::kBasePointerOffset,
5992 Representation::Tagged());
5993 }
5994
5995 static HObjectAccess ForFixedTypedArrayBaseExternalPointer() {
5996 return HObjectAccess::ForObservableJSObjectOffset(
5997 FixedTypedArrayBase::kExternalPointerOffset,
5998 Representation::External());
5999 }
6000
6001 static HObjectAccess ForStringHashField() {
6002 return HObjectAccess(kInobject,
6003 String::kHashFieldOffset,
6004 Representation::Integer32());
6005 }
6006
6007 static HObjectAccess ForStringLength() {
6008 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
6009 return HObjectAccess(
6010 kStringLengths,
6011 String::kLengthOffset,
6012 Representation::Smi());
6013 }
6014
6015 static HObjectAccess ForConsStringFirst() {
6016 return HObjectAccess(kInobject, ConsString::kFirstOffset);
6017 }
6018
6019 static HObjectAccess ForConsStringSecond() {
6020 return HObjectAccess(kInobject, ConsString::kSecondOffset);
6021 }
6022
6023 static HObjectAccess ForPropertiesPointer() {
6024 return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
6025 }
6026
6027 static HObjectAccess ForPrototypeOrInitialMap() {
6028 return HObjectAccess(kInobject, JSFunction::kPrototypeOrInitialMapOffset);
6029 }
6030
6031 static HObjectAccess ForSharedFunctionInfoPointer() {
6032 return HObjectAccess(kInobject, JSFunction::kSharedFunctionInfoOffset);
6033 }
6034
6035 static HObjectAccess ForCodeEntryPointer() {
6036 return HObjectAccess(kInobject, JSFunction::kCodeEntryOffset);
6037 }
6038
6039 static HObjectAccess ForCodeOffset() {
6040 return HObjectAccess(kInobject, SharedFunctionInfo::kCodeOffset);
6041 }
6042
6043 static HObjectAccess ForOptimizedCodeMap() {
6044 return HObjectAccess(kInobject,
6045 SharedFunctionInfo::kOptimizedCodeMapOffset);
6046 }
6047
6048 static HObjectAccess ForOptimizedCodeMapSharedCode() {
6049 return HObjectAccess(kInobject, FixedArray::OffsetOfElementAt(
6050 SharedFunctionInfo::kSharedCodeIndex));
6051 }
6052
6053 static HObjectAccess ForFunctionContextPointer() {
6054 return HObjectAccess(kInobject, JSFunction::kContextOffset);
6055 }
6056
6057 static HObjectAccess ForMap() {
6058 return HObjectAccess(kMaps, JSObject::kMapOffset);
6059 }
6060
6061 static HObjectAccess ForPrototype() {
6062 return HObjectAccess(kMaps, Map::kPrototypeOffset);
6063 }
6064
6065 static HObjectAccess ForMapAsInteger32() {
6066 return HObjectAccess(kMaps, JSObject::kMapOffset,
6067 Representation::Integer32());
6068 }
6069
6070 static HObjectAccess ForMapInObjectPropertiesOrConstructorFunctionIndex() {
6071 return HObjectAccess(
6072 kInobject, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset,
6073 Representation::UInteger8());
6074 }
6075
6076 static HObjectAccess ForMapInstanceType() {
6077 return HObjectAccess(kInobject,
6078 Map::kInstanceTypeOffset,
6079 Representation::UInteger8());
6080 }
6081
6082 static HObjectAccess ForMapInstanceSize() {
6083 return HObjectAccess(kInobject,
6084 Map::kInstanceSizeOffset,
6085 Representation::UInteger8());
6086 }
6087
6088 static HObjectAccess ForMapBitField() {
6089 return HObjectAccess(kInobject,
6090 Map::kBitFieldOffset,
6091 Representation::UInteger8());
6092 }
6093
6094 static HObjectAccess ForMapBitField2() {
6095 return HObjectAccess(kInobject,
6096 Map::kBitField2Offset,
6097 Representation::UInteger8());
6098 }
6099
6100 static HObjectAccess ForNameHashField() {
6101 return HObjectAccess(kInobject,
6102 Name::kHashFieldOffset,
6103 Representation::Integer32());
6104 }
6105
6106 static HObjectAccess ForMapInstanceTypeAndBitField() {
6107 STATIC_ASSERT((Map::kInstanceTypeAndBitFieldOffset & 1) == 0);
6108 // Ensure the two fields share one 16-bit word, endian-independent.
6109 STATIC_ASSERT((Map::kBitFieldOffset & ~1) ==
6110 (Map::kInstanceTypeOffset & ~1));
6111 return HObjectAccess(kInobject,
6112 Map::kInstanceTypeAndBitFieldOffset,
6113 Representation::UInteger16());
6114 }
6115
6116 static HObjectAccess ForPropertyCellValue() {
6117 return HObjectAccess(kInobject, PropertyCell::kValueOffset);
6118 }
6119
6120 static HObjectAccess ForPropertyCellDetails() {
6121 return HObjectAccess(kInobject, PropertyCell::kDetailsOffset,
6122 Representation::Smi());
6123 }
6124
6125 static HObjectAccess ForCellValue() {
6126 return HObjectAccess(kInobject, Cell::kValueOffset);
6127 }
6128
6129 static HObjectAccess ForWeakCellValue() {
6130 return HObjectAccess(kInobject, WeakCell::kValueOffset);
6131 }
6132
6133 static HObjectAccess ForWeakCellNext() {
6134 return HObjectAccess(kInobject, WeakCell::kNextOffset);
6135 }
6136
6137 static HObjectAccess ForAllocationMementoSite() {
6138 return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset);
6139 }
6140
6141 static HObjectAccess ForCounter() {
6142 return HObjectAccess(kExternalMemory, 0, Representation::Integer32(),
6143 Handle<Name>::null(), false, false);
6144 }
6145
6146 static HObjectAccess ForExternalUInteger8() {
6147 return HObjectAccess(kExternalMemory, 0, Representation::UInteger8(),
6148 Handle<Name>::null(), false, false);
6149 }
6150
6151 // Create an access to an offset in a fixed array header.
6152 static HObjectAccess ForFixedArrayHeader(int offset);
6153
6154 // Create an access to an in-object property in a JSObject.
6155 // This kind of access must be used when the object |map| is known and
6156 // in-object properties are being accessed. Accesses of the in-object
6157 // properties can have different semantics depending on whether corresponding
6158 // property was added to the map or not.
6159 static HObjectAccess ForMapAndOffset(Handle<Map> map, int offset,
6160 Representation representation = Representation::Tagged());
6161
6162 // Create an access to an in-object property in a JSObject.
6163 // This kind of access can be used for accessing object header fields or
6164 // in-object properties if the map of the object is not known.
6165 static HObjectAccess ForObservableJSObjectOffset(int offset,
6166 Representation representation = Representation::Tagged()) {
6167 return ForMapAndOffset(Handle<Map>::null(), offset, representation);
6168 }
6169
6170 // Create an access to an in-object property in a JSArray.
6171 static HObjectAccess ForJSArrayOffset(int offset);
6172
6173 static HObjectAccess ForContextSlot(int index);
6174
6175 static HObjectAccess ForScriptContext(int index);
6176
6177 // Create an access to the backing store of an object.
6178 static HObjectAccess ForBackingStoreOffset(int offset,
6179 Representation representation = Representation::Tagged());
6180
6181 // Create an access to a resolved field (in-object or backing store).
6182 static HObjectAccess ForField(Handle<Map> map, int index,
6183 Representation representation,
6184 Handle<Name> name);
6185
6186 static HObjectAccess ForJSTypedArrayLength() {
6187 return HObjectAccess::ForObservableJSObjectOffset(
6188 JSTypedArray::kLengthOffset);
6189 }
6190
6191 static HObjectAccess ForJSArrayBufferBackingStore() {
6192 return HObjectAccess::ForObservableJSObjectOffset(
6193 JSArrayBuffer::kBackingStoreOffset, Representation::External());
6194 }
6195
6196 static HObjectAccess ForJSArrayBufferByteLength() {
6197 return HObjectAccess::ForObservableJSObjectOffset(
6198 JSArrayBuffer::kByteLengthOffset, Representation::Tagged());
6199 }
6200
6201 static HObjectAccess ForJSArrayBufferBitField() {
6202 return HObjectAccess::ForObservableJSObjectOffset(
6203 JSArrayBuffer::kBitFieldOffset, Representation::Integer32());
6204 }
6205
6206 static HObjectAccess ForJSArrayBufferBitFieldSlot() {
6207 return HObjectAccess::ForObservableJSObjectOffset(
6208 JSArrayBuffer::kBitFieldSlot, Representation::Smi());
6209 }
6210
6211 static HObjectAccess ForJSArrayBufferViewBuffer() {
6212 return HObjectAccess::ForObservableJSObjectOffset(
6213 JSArrayBufferView::kBufferOffset);
6214 }
6215
6216 static HObjectAccess ForJSArrayBufferViewByteOffset() {
6217 return HObjectAccess::ForObservableJSObjectOffset(
6218 JSArrayBufferView::kByteOffsetOffset);
6219 }
6220
6221 static HObjectAccess ForJSArrayBufferViewByteLength() {
6222 return HObjectAccess::ForObservableJSObjectOffset(
6223 JSArrayBufferView::kByteLengthOffset);
6224 }
6225
6226 static HObjectAccess ForGlobalObjectNativeContext() {
6227 return HObjectAccess(kInobject, GlobalObject::kNativeContextOffset);
6228 }
6229
6230 static HObjectAccess ForJSCollectionTable() {
6231 return HObjectAccess::ForObservableJSObjectOffset(
6232 JSCollection::kTableOffset);
6233 }
6234
6235 template <typename CollectionType>
6236 static HObjectAccess ForOrderedHashTableNumberOfBuckets() {
6237 return HObjectAccess(kInobject, CollectionType::kNumberOfBucketsOffset,
6238 Representation::Smi());
6239 }
6240
6241 template <typename CollectionType>
6242 static HObjectAccess ForOrderedHashTableNumberOfElements() {
6243 return HObjectAccess(kInobject, CollectionType::kNumberOfElementsOffset,
6244 Representation::Smi());
6245 }
6246
6247 template <typename CollectionType>
6248 static HObjectAccess ForOrderedHashTableNumberOfDeletedElements() {
6249 return HObjectAccess(kInobject,
6250 CollectionType::kNumberOfDeletedElementsOffset,
6251 Representation::Smi());
6252 }
6253
6254 template <typename CollectionType>
6255 static HObjectAccess ForOrderedHashTableNextTable() {
6256 return HObjectAccess(kInobject, CollectionType::kNextTableOffset);
6257 }
6258
6259 template <typename CollectionType>
6260 static HObjectAccess ForOrderedHashTableBucket(int bucket) {
6261 return HObjectAccess(kInobject, CollectionType::kHashTableStartOffset +
6262 (bucket * kPointerSize),
6263 Representation::Smi());
6264 }
6265
6266 // Access into the data table of an OrderedHashTable with a
6267 // known-at-compile-time bucket count.
6268 template <typename CollectionType, int kBucketCount>
6269 static HObjectAccess ForOrderedHashTableDataTableIndex(int index) {
6270 return HObjectAccess(kInobject, CollectionType::kHashTableStartOffset +
6271 (kBucketCount * kPointerSize) +
6272 (index * kPointerSize));
6273 }
6274
6275 inline bool Equals(HObjectAccess that) const {
6276 return value_ == that.value_; // portion and offset must match
6277 }
6278
6279 protected:
6280 void SetGVNFlags(HValue *instr, PropertyAccessType access_type);
6281
6282 private:
6283 // internal use only; different parts of an object or array
6284 enum Portion {
6285 kMaps, // map of an object
6286 kArrayLengths, // the length of an array
6287 kStringLengths, // the length of a string
6288 kElementsPointer, // elements pointer
6289 kBackingStore, // some field in the backing store
6290 kDouble, // some double field
6291 kInobject, // some other in-object field
6292 kExternalMemory // some field in external memory
6293 };
6294
6295 HObjectAccess() : value_(0) {}
6296
6297 HObjectAccess(Portion portion, int offset,
6298 Representation representation = Representation::Tagged(),
6299 Handle<Name> name = Handle<Name>::null(),
6300 bool immutable = false, bool existing_inobject_property = true)
6301 : value_(PortionField::encode(portion) |
6302 RepresentationField::encode(representation.kind()) |
6303 ImmutableField::encode(immutable ? 1 : 0) |
6304 ExistingInobjectPropertyField::encode(
6305 existing_inobject_property ? 1 : 0) |
6306 OffsetField::encode(offset)),
6307 name_(name) {
6308 // assert that the fields decode correctly
6309 DCHECK(this->offset() == offset);
6310 DCHECK(this->portion() == portion);
6311 DCHECK(this->immutable() == immutable);
6312 DCHECK(this->existing_inobject_property() == existing_inobject_property);
6313 DCHECK(RepresentationField::decode(value_) == representation.kind());
6314 DCHECK(!this->existing_inobject_property() || IsInobject());
6315 }
6316
6317 class PortionField : public BitField<Portion, 0, 3> {};
6318 class RepresentationField : public BitField<Representation::Kind, 3, 4> {};
6319 class ImmutableField : public BitField<bool, 7, 1> {};
6320 class ExistingInobjectPropertyField : public BitField<bool, 8, 1> {};
6321 class OffsetField : public BitField<int, 9, 23> {};
6322
6323 uint32_t value_; // encodes portion, representation, immutable, and offset
6324 Handle<Name> name_;
6325
6326 friend class HLoadNamedField;
6327 friend class HStoreNamedField;
6328 friend class SideEffectsTracker;
6329 friend std::ostream& operator<<(std::ostream& os,
6330 const HObjectAccess& access);
6331
6332 inline Portion portion() const {
6333 return PortionField::decode(value_);
6334 }
6335 };
6336
6337
6338 std::ostream& operator<<(std::ostream& os, const HObjectAccess& access);
6339
6340
6341 class HLoadNamedField final : public HTemplateInstruction<2> {
6342 public:
6343 DECLARE_INSTRUCTION_FACTORY_P3(HLoadNamedField, HValue*,
6344 HValue*, HObjectAccess);
6345 DECLARE_INSTRUCTION_FACTORY_P5(HLoadNamedField, HValue*, HValue*,
6346 HObjectAccess, const UniqueSet<Map>*, HType);
6347
6348 HValue* object() const { return OperandAt(0); }
6349 HValue* dependency() const {
6350 DCHECK(HasDependency());
6351 return OperandAt(1);
6352 }
6353 bool HasDependency() const { return OperandAt(0) != OperandAt(1); }
6354 HObjectAccess access() const { return access_; }
6355 Representation field_representation() const {
6356 return access_.representation();
6357 }
6358
6359 const UniqueSet<Map>* maps() const { return maps_; }
6360
6361 bool HasEscapingOperandAt(int index) override { return false; }
6362 bool HasOutOfBoundsAccess(int size) override {
6363 return !access().IsInobject() || access().offset() >= size;
6364 }
6365 Representation RequiredInputRepresentation(int index) override {
6366 if (index == 0) {
6367 // object must be external in case of external memory access
6368 return access().IsExternalMemory() ? Representation::External()
6369 : Representation::Tagged();
6370 }
6371 DCHECK(index == 1);
6372 return Representation::None();
6373 }
6374 Range* InferRange(Zone* zone) override;
6375 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
6376
6377 bool CanBeReplacedWith(HValue* other) const {
6378 if (!CheckFlag(HValue::kCantBeReplaced)) return false;
6379 if (!type().Equals(other->type())) return false;
6380 if (!representation().Equals(other->representation())) return false;
6381 if (!other->IsLoadNamedField()) return true;
6382 HLoadNamedField* that = HLoadNamedField::cast(other);
6383 if (this->maps_ == that->maps_) return true;
6384 if (this->maps_ == NULL || that->maps_ == NULL) return false;
6385 return this->maps_->IsSubset(that->maps_);
6386 }
6387
6388 DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
6389
6390 protected:
6391 bool DataEquals(HValue* other) override {
6392 HLoadNamedField* that = HLoadNamedField::cast(other);
6393 if (!this->access_.Equals(that->access_)) return false;
6394 if (this->maps_ == that->maps_) return true;
6395 return (this->maps_ != NULL &&
6396 that->maps_ != NULL &&
6397 this->maps_->Equals(that->maps_));
6398 }
6399
6400 private:
6401 HLoadNamedField(HValue* object,
6402 HValue* dependency,
6403 HObjectAccess access)
6404 : access_(access), maps_(NULL) {
6405 DCHECK_NOT_NULL(object);
6406 SetOperandAt(0, object);
6407 SetOperandAt(1, dependency ? dependency : object);
6408
6409 Representation representation = access.representation();
6410 if (representation.IsInteger8() ||
6411 representation.IsUInteger8() ||
6412 representation.IsInteger16() ||
6413 representation.IsUInteger16()) {
6414 set_representation(Representation::Integer32());
6415 } else if (representation.IsSmi()) {
6416 set_type(HType::Smi());
6417 if (SmiValuesAre32Bits()) {
6418 set_representation(Representation::Integer32());
6419 } else {
6420 set_representation(representation);
6421 }
6422 } else if (representation.IsDouble() ||
6423 representation.IsExternal() ||
6424 representation.IsInteger32()) {
6425 set_representation(representation);
6426 } else if (representation.IsHeapObject()) {
6427 set_type(HType::HeapObject());
6428 set_representation(Representation::Tagged());
6429 } else {
6430 set_representation(Representation::Tagged());
6431 }
6432 access.SetGVNFlags(this, LOAD);
6433 }
6434
6435 HLoadNamedField(HValue* object,
6436 HValue* dependency,
6437 HObjectAccess access,
6438 const UniqueSet<Map>* maps,
6439 HType type)
6440 : HTemplateInstruction<2>(type), access_(access), maps_(maps) {
6441 DCHECK_NOT_NULL(maps);
6442 DCHECK_NE(0, maps->size());
6443
6444 DCHECK_NOT_NULL(object);
6445 SetOperandAt(0, object);
6446 SetOperandAt(1, dependency ? dependency : object);
6447
6448 DCHECK(access.representation().IsHeapObject());
6449 DCHECK(type.IsHeapObject());
6450 set_representation(Representation::Tagged());
6451
6452 access.SetGVNFlags(this, LOAD);
6453 }
6454
6455 bool IsDeletable() const override { return true; }
6456
6457 HObjectAccess access_;
6458 const UniqueSet<Map>* maps_;
6459 };
6460
6461
6462 class HLoadNamedGeneric final : public HTemplateInstruction<2> {
6463 public:
6464 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HLoadNamedGeneric, HValue*,
6465 Handle<Name>, LanguageMode,
6466 InlineCacheState);
6467
6468 HValue* context() const { return OperandAt(0); }
6469 HValue* object() const { return OperandAt(1); }
6470 Handle<Name> name() const { return name_; }
6471
6472 InlineCacheState initialization_state() const {
6473 return initialization_state_;
6474 }
6475 FeedbackVectorSlot slot() const { return slot_; }
6476 Handle<TypeFeedbackVector> feedback_vector() const {
6477 return feedback_vector_;
6478 }
6479 bool HasVectorAndSlot() const { return true; }
6480 void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
6481 FeedbackVectorSlot slot) {
6482 feedback_vector_ = vector;
6483 slot_ = slot;
6484 }
6485
6486 Representation RequiredInputRepresentation(int index) override {
6487 return Representation::Tagged();
6488 }
6489
6490 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
6491
6492 DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
6493
6494 LanguageMode language_mode() const { return language_mode_; }
6495
6496 private:
6497 HLoadNamedGeneric(HValue* context, HValue* object, Handle<Name> name,
6498 LanguageMode language_mode,
6499 InlineCacheState initialization_state)
6500 : name_(name),
6501 language_mode_(language_mode),
6502 initialization_state_(initialization_state) {
6503 SetOperandAt(0, context);
6504 SetOperandAt(1, object);
6505 set_representation(Representation::Tagged());
6506 SetAllSideEffects();
6507 }
6508
6509 Handle<Name> name_;
6510 Handle<TypeFeedbackVector> feedback_vector_;
6511 FeedbackVectorSlot slot_;
6512 LanguageMode language_mode_;
6513 InlineCacheState initialization_state_;
6514 };
6515
6516
6517 class HLoadFunctionPrototype final : public HUnaryOperation {
6518 public:
6519 DECLARE_INSTRUCTION_FACTORY_P1(HLoadFunctionPrototype, HValue*);
6520
6521 HValue* function() { return OperandAt(0); }
6522
6523 Representation RequiredInputRepresentation(int index) override {
6524 return Representation::Tagged();
6525 }
6526
6527 DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
6528
6529 protected:
6530 bool DataEquals(HValue* other) override { return true; }
6531
6532 private:
6533 explicit HLoadFunctionPrototype(HValue* function)
6534 : HUnaryOperation(function) {
6535 set_representation(Representation::Tagged());
6536 SetFlag(kUseGVN);
6537 SetDependsOnFlag(kCalls);
6538 }
6539 };
6540
6541 class ArrayInstructionInterface {
6542 public:
6543 virtual HValue* GetKey() = 0;
6544 virtual void SetKey(HValue* key) = 0;
6545 virtual ElementsKind elements_kind() const = 0;
6546 // TryIncreaseBaseOffset returns false if overflow would result.
6547 virtual bool TryIncreaseBaseOffset(uint32_t increase_by_value) = 0;
6548 virtual bool IsDehoisted() const = 0;
6549 virtual void SetDehoisted(bool is_dehoisted) = 0;
6550 virtual ~ArrayInstructionInterface() { }
6551
6552 static Representation KeyedAccessIndexRequirement(Representation r) {
6553 return r.IsInteger32() || SmiValuesAre32Bits()
6554 ? Representation::Integer32() : Representation::Smi();
6555 }
6556 };
6557
6558
6559 static const int kDefaultKeyedHeaderOffsetSentinel = -1;
6560
6561 enum LoadKeyedHoleMode {
6562 NEVER_RETURN_HOLE,
6563 ALLOW_RETURN_HOLE,
6564 CONVERT_HOLE_TO_UNDEFINED
6565 };
6566
6567
6568 class HLoadKeyed final : public HTemplateInstruction<3>,
6569 public ArrayInstructionInterface {
6570 public:
6571 DECLARE_INSTRUCTION_FACTORY_P4(HLoadKeyed, HValue*, HValue*, HValue*,
6572 ElementsKind);
6573 DECLARE_INSTRUCTION_FACTORY_P5(HLoadKeyed, HValue*, HValue*, HValue*,
6574 ElementsKind, LoadKeyedHoleMode);
6575 DECLARE_INSTRUCTION_FACTORY_P6(HLoadKeyed, HValue*, HValue*, HValue*,
6576 ElementsKind, LoadKeyedHoleMode, int);
6577
6578 bool is_fixed_typed_array() const {
6579 return IsFixedTypedArrayElementsKind(elements_kind());
6580 }
6581 HValue* elements() const { return OperandAt(0); }
6582 HValue* key() const { return OperandAt(1); }
6583 HValue* dependency() const {
6584 DCHECK(HasDependency());
6585 return OperandAt(2);
6586 }
6587 bool HasDependency() const { return OperandAt(0) != OperandAt(2); }
6588 uint32_t base_offset() const { return BaseOffsetField::decode(bit_field_); }
6589 bool TryIncreaseBaseOffset(uint32_t increase_by_value) override;
6590 HValue* GetKey() override { return key(); }
6591 void SetKey(HValue* key) override { SetOperandAt(1, key); }
6592 bool IsDehoisted() const override {
6593 return IsDehoistedField::decode(bit_field_);
6594 }
6595 void SetDehoisted(bool is_dehoisted) override {
6596 bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
6597 }
6598 ElementsKind elements_kind() const override {
6599 return ElementsKindField::decode(bit_field_);
6600 }
6601 LoadKeyedHoleMode hole_mode() const {
6602 return HoleModeField::decode(bit_field_);
6603 }
6604
6605 Representation RequiredInputRepresentation(int index) override {
6606 // kind_fast: tagged[int32] (none)
6607 // kind_double: tagged[int32] (none)
6608 // kind_fixed_typed_array: external[int32] (none)
6609 // kind_external: external[int32] (none)
6610 if (index == 0) {
6611 return is_fixed_typed_array() ? Representation::External()
6612 : Representation::Tagged();
6613 }
6614 if (index == 1) {
6615 return ArrayInstructionInterface::KeyedAccessIndexRequirement(
6616 OperandAt(1)->representation());
6617 }
6618 return Representation::None();
6619 }
6620
6621 Representation observed_input_representation(int index) override {
6622 return RequiredInputRepresentation(index);
6623 }
6624
6625 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
6626
6627 bool UsesMustHandleHole() const;
6628 bool AllUsesCanTreatHoleAsNaN() const;
6629 bool RequiresHoleCheck() const;
6630
6631 Range* InferRange(Zone* zone) override;
6632
6633 DECLARE_CONCRETE_INSTRUCTION(LoadKeyed)
6634
6635 protected:
6636 bool DataEquals(HValue* other) override {
6637 if (!other->IsLoadKeyed()) return false;
6638 HLoadKeyed* other_load = HLoadKeyed::cast(other);
6639
6640 if (base_offset() != other_load->base_offset()) return false;
6641 return elements_kind() == other_load->elements_kind();
6642 }
6643
6644 private:
6645 HLoadKeyed(HValue* obj, HValue* key, HValue* dependency,
6646 ElementsKind elements_kind,
6647 LoadKeyedHoleMode mode = NEVER_RETURN_HOLE,
6648 int offset = kDefaultKeyedHeaderOffsetSentinel)
6649 : bit_field_(0) {
6650 offset = offset == kDefaultKeyedHeaderOffsetSentinel
6651 ? GetDefaultHeaderSizeForElementsKind(elements_kind)
6652 : offset;
6653 bit_field_ = ElementsKindField::encode(elements_kind) |
6654 HoleModeField::encode(mode) |
6655 BaseOffsetField::encode(offset);
6656
6657 SetOperandAt(0, obj);
6658 SetOperandAt(1, key);
6659 SetOperandAt(2, dependency != NULL ? dependency : obj);
6660
6661 if (!is_fixed_typed_array()) {
6662 // I can detect the case between storing double (holey and fast) and
6663 // smi/object by looking at elements_kind_.
6664 DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
6665 IsFastDoubleElementsKind(elements_kind));
6666
6667 if (IsFastSmiOrObjectElementsKind(elements_kind)) {
6668 if (IsFastSmiElementsKind(elements_kind) &&
6669 (!IsHoleyElementsKind(elements_kind) ||
6670 mode == NEVER_RETURN_HOLE)) {
6671 set_type(HType::Smi());
6672 if (SmiValuesAre32Bits() && !RequiresHoleCheck()) {
6673 set_representation(Representation::Integer32());
6674 } else {
6675 set_representation(Representation::Smi());
6676 }
6677 } else {
6678 set_representation(Representation::Tagged());
6679 }
6680
6681 SetDependsOnFlag(kArrayElements);
6682 } else {
6683 set_representation(Representation::Double());
6684 SetDependsOnFlag(kDoubleArrayElements);
6685 }
6686 } else {
6687 if (elements_kind == FLOAT32_ELEMENTS ||
6688 elements_kind == FLOAT64_ELEMENTS) {
6689 set_representation(Representation::Double());
6690 } else {
6691 set_representation(Representation::Integer32());
6692 }
6693
6694 if (is_fixed_typed_array()) {
6695 SetDependsOnFlag(kExternalMemory);
6696 SetDependsOnFlag(kTypedArrayElements);
6697 } else {
6698 UNREACHABLE();
6699 }
6700 // Native code could change the specialized array.
6701 SetDependsOnFlag(kCalls);
6702 }
6703
6704 SetFlag(kUseGVN);
6705 }
6706
6707 bool IsDeletable() const override { return !RequiresHoleCheck(); }
6708
6709 // Establish some checks around our packed fields
6710 enum LoadKeyedBits {
6711 kBitsForElementsKind = 5,
6712 kBitsForHoleMode = 2,
6713 kBitsForBaseOffset = 24,
6714 kBitsForIsDehoisted = 1,
6715
6716 kStartElementsKind = 0,
6717 kStartHoleMode = kStartElementsKind + kBitsForElementsKind,
6718 kStartBaseOffset = kStartHoleMode + kBitsForHoleMode,
6719 kStartIsDehoisted = kStartBaseOffset + kBitsForBaseOffset
6720 };
6721
6722 STATIC_ASSERT((kBitsForElementsKind + kBitsForHoleMode + kBitsForBaseOffset +
6723 kBitsForIsDehoisted) <= sizeof(uint32_t) * 8);
6724 STATIC_ASSERT(kElementsKindCount <= (1 << kBitsForElementsKind));
6725 class ElementsKindField:
6726 public BitField<ElementsKind, kStartElementsKind, kBitsForElementsKind>
6727 {}; // NOLINT
6728 class HoleModeField:
6729 public BitField<LoadKeyedHoleMode, kStartHoleMode, kBitsForHoleMode>
6730 {}; // NOLINT
6731 class BaseOffsetField:
6732 public BitField<uint32_t, kStartBaseOffset, kBitsForBaseOffset>
6733 {}; // NOLINT
6734 class IsDehoistedField:
6735 public BitField<bool, kStartIsDehoisted, kBitsForIsDehoisted>
6736 {}; // NOLINT
6737 uint32_t bit_field_;
6738 };
6739
6740
6741 class HLoadKeyedGeneric final : public HTemplateInstruction<3> {
6742 public:
6743 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HLoadKeyedGeneric, HValue*,
6744 HValue*, LanguageMode,
6745 InlineCacheState);
6746 HValue* object() const { return OperandAt(0); }
6747 HValue* key() const { return OperandAt(1); }
6748 HValue* context() const { return OperandAt(2); }
6749 InlineCacheState initialization_state() const {
6750 return initialization_state_;
6751 }
6752 FeedbackVectorSlot slot() const { return slot_; }
6753 Handle<TypeFeedbackVector> feedback_vector() const {
6754 return feedback_vector_;
6755 }
6756 bool HasVectorAndSlot() const {
6757 DCHECK(initialization_state_ == MEGAMORPHIC || !feedback_vector_.is_null());
6758 return !feedback_vector_.is_null();
6759 }
6760 void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
6761 FeedbackVectorSlot slot) {
6762 feedback_vector_ = vector;
6763 slot_ = slot;
6764 }
6765
6766 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
6767
6768 Representation RequiredInputRepresentation(int index) override {
6769 // tagged[tagged]
6770 return Representation::Tagged();
6771 }
6772
6773 HValue* Canonicalize() override;
6774
6775 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric)
6776
6777 LanguageMode language_mode() const { return language_mode_; }
6778
6779 private:
6780 HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key,
6781 LanguageMode language_mode,
6782 InlineCacheState initialization_state)
6783 : initialization_state_(initialization_state),
6784 language_mode_(language_mode) {
6785 set_representation(Representation::Tagged());
6786 SetOperandAt(0, obj);
6787 SetOperandAt(1, key);
6788 SetOperandAt(2, context);
6789 SetAllSideEffects();
6790 }
6791
6792 Handle<TypeFeedbackVector> feedback_vector_;
6793 FeedbackVectorSlot slot_;
6794 InlineCacheState initialization_state_;
6795 LanguageMode language_mode_;
6796 };
6797
6798
6799 // Indicates whether the store is a store to an entry that was previously
6800 // initialized or not.
6801 enum StoreFieldOrKeyedMode {
6802 // The entry could be either previously initialized or not.
6803 INITIALIZING_STORE,
6804 // At the time of this store it is guaranteed that the entry is already
6805 // initialized.
6806 STORE_TO_INITIALIZED_ENTRY
6807 };
6808
6809
6810 class HStoreNamedField final : public HTemplateInstruction<3> {
6811 public:
6812 DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*,
6813 HObjectAccess, HValue*);
6814 DECLARE_INSTRUCTION_FACTORY_P4(HStoreNamedField, HValue*,
6815 HObjectAccess, HValue*, StoreFieldOrKeyedMode);
6816
6817 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
6818
6819 bool HasEscapingOperandAt(int index) override { return index == 1; }
6820 bool HasOutOfBoundsAccess(int size) override {
6821 return !access().IsInobject() || access().offset() >= size;
6822 }
6823 Representation RequiredInputRepresentation(int index) override {
6824 if (index == 0 && access().IsExternalMemory()) {
6825 // object must be external in case of external memory access
6826 return Representation::External();
6827 } else if (index == 1) {
6828 if (field_representation().IsInteger8() ||
6829 field_representation().IsUInteger8() ||
6830 field_representation().IsInteger16() ||
6831 field_representation().IsUInteger16() ||
6832 field_representation().IsInteger32()) {
6833 return Representation::Integer32();
6834 } else if (field_representation().IsDouble()) {
6835 return field_representation();
6836 } else if (field_representation().IsSmi()) {
6837 if (SmiValuesAre32Bits() &&
6838 store_mode() == STORE_TO_INITIALIZED_ENTRY) {
6839 return Representation::Integer32();
6840 }
6841 return field_representation();
6842 } else if (field_representation().IsExternal()) {
6843 return Representation::External();
6844 }
6845 }
6846 return Representation::Tagged();
6847 }
6848 virtual bool HandleSideEffectDominator(GVNFlag side_effect,
6849 HValue* dominator) override {
6850 DCHECK(side_effect == kNewSpacePromotion);
6851 if (!FLAG_use_write_barrier_elimination) return false;
6852 dominator_ = dominator;
6853 return false;
6854 }
6855 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
6856
6857 HValue* object() const { return OperandAt(0); }
6858 HValue* value() const { return OperandAt(1); }
6859 HValue* transition() const { return OperandAt(2); }
6860
6861 HObjectAccess access() const { return access_; }
6862 HValue* dominator() const { return dominator_; }
6863 bool has_transition() const { return HasTransitionField::decode(bit_field_); }
6864 StoreFieldOrKeyedMode store_mode() const {
6865 return StoreModeField::decode(bit_field_);
6866 }
6867
6868 Handle<Map> transition_map() const {
6869 if (has_transition()) {
6870 return Handle<Map>::cast(
6871 HConstant::cast(transition())->handle(isolate()));
6872 } else {
6873 return Handle<Map>();
6874 }
6875 }
6876
6877 void SetTransition(HConstant* transition) {
6878 DCHECK(!has_transition()); // Only set once.
6879 SetOperandAt(2, transition);
6880 bit_field_ = HasTransitionField::update(bit_field_, true);
6881 SetChangesFlag(kMaps);
6882 }
6883
6884 bool NeedsWriteBarrier() const {
6885 DCHECK(!field_representation().IsDouble() ||
6886 (FLAG_unbox_double_fields && access_.IsInobject()) ||
6887 !has_transition());
6888 if (field_representation().IsDouble()) return false;
6889 if (field_representation().IsSmi()) return false;
6890 if (field_representation().IsInteger32()) return false;
6891 if (field_representation().IsExternal()) return false;
6892 return StoringValueNeedsWriteBarrier(value()) &&
6893 ReceiverObjectNeedsWriteBarrier(object(), value(), dominator());
6894 }
6895
6896 bool NeedsWriteBarrierForMap() {
6897 return ReceiverObjectNeedsWriteBarrier(object(), transition(),
6898 dominator());
6899 }
6900
6901 SmiCheck SmiCheckForWriteBarrier() const {
6902 if (field_representation().IsHeapObject()) return OMIT_SMI_CHECK;
6903 if (value()->type().IsHeapObject()) return OMIT_SMI_CHECK;
6904 return INLINE_SMI_CHECK;
6905 }
6906
6907 PointersToHereCheck PointersToHereCheckForValue() const {
6908 return PointersToHereCheckForObject(value(), dominator());
6909 }
6910
6911 Representation field_representation() const {
6912 return access_.representation();
6913 }
6914
6915 void UpdateValue(HValue* value) {
6916 SetOperandAt(1, value);
6917 }
6918
6919 bool CanBeReplacedWith(HStoreNamedField* that) const {
6920 if (!this->access().Equals(that->access())) return false;
6921 if (SmiValuesAre32Bits() &&
6922 this->field_representation().IsSmi() &&
6923 this->store_mode() == INITIALIZING_STORE &&
6924 that->store_mode() == STORE_TO_INITIALIZED_ENTRY) {
6925 // We cannot replace an initializing store to a smi field with a store to
6926 // an initialized entry on 64-bit architectures (with 32-bit smis).
6927 return false;
6928 }
6929 return true;
6930 }
6931
6932 private:
6933 HStoreNamedField(HValue* obj, HObjectAccess access, HValue* val,
6934 StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE)
6935 : access_(access),
6936 dominator_(NULL),
6937 bit_field_(HasTransitionField::encode(false) |
6938 StoreModeField::encode(store_mode)) {
6939 // Stores to a non existing in-object property are allowed only to the
6940 // newly allocated objects (via HAllocate or HInnerAllocatedObject).
6941 DCHECK(!access.IsInobject() || access.existing_inobject_property() ||
6942 obj->IsAllocate() || obj->IsInnerAllocatedObject());
6943 SetOperandAt(0, obj);
6944 SetOperandAt(1, val);
6945 SetOperandAt(2, obj);
6946 access.SetGVNFlags(this, STORE);
6947 }
6948
6949 class HasTransitionField : public BitField<bool, 0, 1> {};
6950 class StoreModeField : public BitField<StoreFieldOrKeyedMode, 1, 1> {};
6951
6952 HObjectAccess access_;
6953 HValue* dominator_;
6954 uint32_t bit_field_;
6955 };
6956
6957
6958 class HStoreNamedGeneric final : public HTemplateInstruction<3> {
6959 public:
6960 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(HStoreNamedGeneric, HValue*,
6961 Handle<Name>, HValue*,
6962 LanguageMode, InlineCacheState);
6963 HValue* object() const { return OperandAt(0); }
6964 HValue* value() const { return OperandAt(1); }
6965 HValue* context() const { return OperandAt(2); }
6966 Handle<Name> name() const { return name_; }
6967 LanguageMode language_mode() const { return language_mode_; }
6968 InlineCacheState initialization_state() const {
6969 return initialization_state_;
6970 }
6971
6972 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
6973
6974 Representation RequiredInputRepresentation(int index) override {
6975 return Representation::Tagged();
6976 }
6977
6978 FeedbackVectorSlot slot() const { return slot_; }
6979 Handle<TypeFeedbackVector> feedback_vector() const {
6980 return feedback_vector_;
6981 }
6982 bool HasVectorAndSlot() const { return FLAG_vector_stores; }
6983 void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
6984 FeedbackVectorSlot slot) {
6985 feedback_vector_ = vector;
6986 slot_ = slot;
6987 }
6988
6989 DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric)
6990
6991 private:
6992 HStoreNamedGeneric(HValue* context, HValue* object, Handle<Name> name,
6993 HValue* value, LanguageMode language_mode,
6994 InlineCacheState initialization_state)
6995 : name_(name),
6996 language_mode_(language_mode),
6997 initialization_state_(initialization_state) {
6998 SetOperandAt(0, object);
6999 SetOperandAt(1, value);
7000 SetOperandAt(2, context);
7001 SetAllSideEffects();
7002 }
7003
7004 Handle<Name> name_;
7005 Handle<TypeFeedbackVector> feedback_vector_;
7006 FeedbackVectorSlot slot_;
7007 LanguageMode language_mode_;
7008 InlineCacheState initialization_state_;
7009 };
7010
7011
7012 class HStoreGlobalViaContext final : public HTemplateInstruction<2> {
7013 public:
7014 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HStoreGlobalViaContext, HValue*,
7015 int, int, LanguageMode);
7016 HValue* context() const { return OperandAt(0); }
7017 HValue* value() const { return OperandAt(1); }
7018 int depth() const { return depth_; }
7019 int slot_index() const { return slot_index_; }
7020 LanguageMode language_mode() const { return language_mode_; }
7021
7022 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
7023
7024 Representation RequiredInputRepresentation(int index) override {
7025 return Representation::Tagged();
7026 }
7027
7028 DECLARE_CONCRETE_INSTRUCTION(StoreGlobalViaContext)
7029
7030 private:
7031 HStoreGlobalViaContext(HValue* context, HValue* value, int depth,
7032 int slot_index, LanguageMode language_mode)
7033 : depth_(depth), slot_index_(slot_index), language_mode_(language_mode) {
7034 SetOperandAt(0, context);
7035 SetOperandAt(1, value);
7036 SetAllSideEffects();
7037 }
7038
7039 int const depth_;
7040 int const slot_index_;
7041 LanguageMode const language_mode_;
7042 };
7043
7044
7045 class HStoreKeyed final : public HTemplateInstruction<3>,
7046 public ArrayInstructionInterface {
7047 public:
7048 DECLARE_INSTRUCTION_FACTORY_P4(HStoreKeyed, HValue*, HValue*, HValue*,
7049 ElementsKind);
7050 DECLARE_INSTRUCTION_FACTORY_P5(HStoreKeyed, HValue*, HValue*, HValue*,
7051 ElementsKind, StoreFieldOrKeyedMode);
7052 DECLARE_INSTRUCTION_FACTORY_P6(HStoreKeyed, HValue*, HValue*, HValue*,
7053 ElementsKind, StoreFieldOrKeyedMode, int);
7054
7055 Representation RequiredInputRepresentation(int index) override {
7056 // kind_fast: tagged[int32] = tagged
7057 // kind_double: tagged[int32] = double
7058 // kind_smi : tagged[int32] = smi
7059 // kind_fixed_typed_array: tagged[int32] = (double | int32)
7060 // kind_external: external[int32] = (double | int32)
7061 if (index == 0) {
7062 return is_fixed_typed_array() ? Representation::External()
7063 : Representation::Tagged();
7064 } else if (index == 1) {
7065 return ArrayInstructionInterface::KeyedAccessIndexRequirement(
7066 OperandAt(1)->representation());
7067 }
7068
7069 DCHECK_EQ(index, 2);
7070 return RequiredValueRepresentation(elements_kind(), store_mode());
7071 }
7072
7073 static Representation RequiredValueRepresentation(
7074 ElementsKind kind, StoreFieldOrKeyedMode mode) {
7075 if (IsDoubleOrFloatElementsKind(kind)) {
7076 return Representation::Double();
7077 }
7078
7079 if (kind == FAST_SMI_ELEMENTS && SmiValuesAre32Bits() &&
7080 mode == STORE_TO_INITIALIZED_ENTRY) {
7081 return Representation::Integer32();
7082 }
7083
7084 if (IsFastSmiElementsKind(kind)) {
7085 return Representation::Smi();
7086 }
7087
7088 if (IsFixedTypedArrayElementsKind(kind)) {
7089 return Representation::Integer32();
7090 }
7091 return Representation::Tagged();
7092 }
7093
7094 bool is_fixed_typed_array() const {
7095 return IsFixedTypedArrayElementsKind(elements_kind());
7096 }
7097
7098 Representation observed_input_representation(int index) override {
7099 if (index < 2) return RequiredInputRepresentation(index);
7100 if (IsUninitialized()) {
7101 return Representation::None();
7102 }
7103 Representation r =
7104 RequiredValueRepresentation(elements_kind(), store_mode());
7105 // For fast object elements kinds, don't assume anything.
7106 if (r.IsTagged()) return Representation::None();
7107 return r;
7108 }
7109
7110 HValue* elements() const { return OperandAt(0); }
7111 HValue* key() const { return OperandAt(1); }
7112 HValue* value() const { return OperandAt(2); }
7113 bool value_is_smi() const { return IsFastSmiElementsKind(elements_kind()); }
7114 StoreFieldOrKeyedMode store_mode() const {
7115 return StoreModeField::decode(bit_field_);
7116 }
7117 ElementsKind elements_kind() const override {
7118 return ElementsKindField::decode(bit_field_);
7119 }
7120 uint32_t base_offset() const { return base_offset_; }
7121 bool TryIncreaseBaseOffset(uint32_t increase_by_value) override;
7122 HValue* GetKey() override { return key(); }
7123 void SetKey(HValue* key) override { SetOperandAt(1, key); }
7124 bool IsDehoisted() const override {
7125 return IsDehoistedField::decode(bit_field_);
7126 }
7127 void SetDehoisted(bool is_dehoisted) override {
7128 bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
7129 }
7130 bool IsUninitialized() { return IsUninitializedField::decode(bit_field_); }
7131 void SetUninitialized(bool is_uninitialized) {
7132 bit_field_ = IsUninitializedField::update(bit_field_, is_uninitialized);
7133 }
7134
7135 bool IsConstantHoleStore() {
7136 return value()->IsConstant() && HConstant::cast(value())->IsTheHole();
7137 }
7138
7139 virtual bool HandleSideEffectDominator(GVNFlag side_effect,
7140 HValue* dominator) override {
7141 DCHECK(side_effect == kNewSpacePromotion);
7142 dominator_ = dominator;
7143 return false;
7144 }
7145
7146 HValue* dominator() const { return dominator_; }
7147
7148 bool NeedsWriteBarrier() {
7149 if (value_is_smi()) {
7150 return false;
7151 } else {
7152 return StoringValueNeedsWriteBarrier(value()) &&
7153 ReceiverObjectNeedsWriteBarrier(elements(), value(), dominator());
7154 }
7155 }
7156
7157 PointersToHereCheck PointersToHereCheckForValue() const {
7158 return PointersToHereCheckForObject(value(), dominator());
7159 }
7160
7161 bool NeedsCanonicalization();
7162
7163 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
7164
7165 DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)
7166
7167 private:
7168 HStoreKeyed(HValue* obj, HValue* key, HValue* val, ElementsKind elements_kind,
7169 StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE,
7170 int offset = kDefaultKeyedHeaderOffsetSentinel)
7171 : base_offset_(offset == kDefaultKeyedHeaderOffsetSentinel
7172 ? GetDefaultHeaderSizeForElementsKind(elements_kind)
7173 : offset),
7174 bit_field_(IsDehoistedField::encode(false) |
7175 IsUninitializedField::encode(false) |
7176 StoreModeField::encode(store_mode) |
7177 ElementsKindField::encode(elements_kind)),
7178 dominator_(NULL) {
7179 SetOperandAt(0, obj);
7180 SetOperandAt(1, key);
7181 SetOperandAt(2, val);
7182
7183 if (IsFastObjectElementsKind(elements_kind)) {
7184 SetFlag(kTrackSideEffectDominators);
7185 SetDependsOnFlag(kNewSpacePromotion);
7186 }
7187 if (IsFastDoubleElementsKind(elements_kind)) {
7188 SetChangesFlag(kDoubleArrayElements);
7189 } else if (IsFastSmiElementsKind(elements_kind)) {
7190 SetChangesFlag(kArrayElements);
7191 } else if (is_fixed_typed_array()) {
7192 SetChangesFlag(kTypedArrayElements);
7193 SetChangesFlag(kExternalMemory);
7194 SetFlag(kAllowUndefinedAsNaN);
7195 } else {
7196 SetChangesFlag(kArrayElements);
7197 }
7198
7199 // {UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
7200 if (elements_kind >= UINT8_ELEMENTS && elements_kind <= INT32_ELEMENTS) {
7201 SetFlag(kTruncatingToInt32);
7202 }
7203 }
7204
7205 class IsDehoistedField : public BitField<bool, 0, 1> {};
7206 class IsUninitializedField : public BitField<bool, 1, 1> {};
7207 class StoreModeField : public BitField<StoreFieldOrKeyedMode, 2, 1> {};
7208 class ElementsKindField : public BitField<ElementsKind, 3, 5> {};
7209
7210 uint32_t base_offset_;
7211 uint32_t bit_field_;
7212 HValue* dominator_;
7213 };
7214
7215
7216 class HStoreKeyedGeneric final : public HTemplateInstruction<4> {
7217 public:
7218 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(HStoreKeyedGeneric, HValue*,
7219 HValue*, HValue*, LanguageMode,
7220 InlineCacheState);
7221
7222 HValue* object() const { return OperandAt(0); }
7223 HValue* key() const { return OperandAt(1); }
7224 HValue* value() const { return OperandAt(2); }
7225 HValue* context() const { return OperandAt(3); }
7226 LanguageMode language_mode() const { return language_mode_; }
7227 InlineCacheState initialization_state() const {
7228 return initialization_state_;
7229 }
7230
7231 Representation RequiredInputRepresentation(int index) override {
7232 // tagged[tagged] = tagged
7233 return Representation::Tagged();
7234 }
7235
7236 FeedbackVectorSlot slot() const { return slot_; }
7237 Handle<TypeFeedbackVector> feedback_vector() const {
7238 return feedback_vector_;
7239 }
7240 bool HasVectorAndSlot() const {
7241 DCHECK(!(FLAG_vector_stores && initialization_state_ != MEGAMORPHIC) ||
7242 !feedback_vector_.is_null());
7243 return !feedback_vector_.is_null();
7244 }
7245 void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
7246 FeedbackVectorSlot slot) {
7247 feedback_vector_ = vector;
7248 slot_ = slot;
7249 }
7250
7251 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
7252
7253 DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric)
7254
7255 private:
7256 HStoreKeyedGeneric(HValue* context, HValue* object, HValue* key,
7257 HValue* value, LanguageMode language_mode,
7258 InlineCacheState initialization_state)
7259 : language_mode_(language_mode),
7260 initialization_state_(initialization_state) {
7261 SetOperandAt(0, object);
7262 SetOperandAt(1, key);
7263 SetOperandAt(2, value);
7264 SetOperandAt(3, context);
7265 SetAllSideEffects();
7266 }
7267
7268 Handle<TypeFeedbackVector> feedback_vector_;
7269 FeedbackVectorSlot slot_;
7270 LanguageMode language_mode_;
7271 InlineCacheState initialization_state_;
7272 };
7273
7274
7275 class HTransitionElementsKind final : public HTemplateInstruction<2> {
7276 public:
7277 inline static HTransitionElementsKind* New(Isolate* isolate, Zone* zone,
7278 HValue* context, HValue* object,
7279 Handle<Map> original_map,
7280 Handle<Map> transitioned_map) {
7281 return new(zone) HTransitionElementsKind(context, object,
7282 original_map, transitioned_map);
7283 }
7284
7285 Representation RequiredInputRepresentation(int index) override {
7286 return Representation::Tagged();
7287 }
7288
7289 HValue* object() const { return OperandAt(0); }
7290 HValue* context() const { return OperandAt(1); }
7291 Unique<Map> original_map() const { return original_map_; }
7292 Unique<Map> transitioned_map() const { return transitioned_map_; }
7293 ElementsKind from_kind() const {
7294 return FromElementsKindField::decode(bit_field_);
7295 }
7296 ElementsKind to_kind() const {
7297 return ToElementsKindField::decode(bit_field_);
7298 }
7299 bool map_is_stable() const { return MapIsStableField::decode(bit_field_); }
7300
7301 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
7302
7303 DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
7304
7305 protected:
7306 bool DataEquals(HValue* other) override {
7307 HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
7308 return original_map_ == instr->original_map_ &&
7309 transitioned_map_ == instr->transitioned_map_;
7310 }
7311
7312 int RedefinedOperandIndex() override { return 0; }
7313
7314 private:
7315 HTransitionElementsKind(HValue* context, HValue* object,
7316 Handle<Map> original_map,
7317 Handle<Map> transitioned_map)
7318 : original_map_(Unique<Map>(original_map)),
7319 transitioned_map_(Unique<Map>(transitioned_map)),
7320 bit_field_(
7321 FromElementsKindField::encode(original_map->elements_kind()) |
7322 ToElementsKindField::encode(transitioned_map->elements_kind()) |
7323 MapIsStableField::encode(transitioned_map->is_stable())) {
7324 SetOperandAt(0, object);
7325 SetOperandAt(1, context);
7326 SetFlag(kUseGVN);
7327 SetChangesFlag(kElementsKind);
7328 if (!IsSimpleMapChangeTransition(from_kind(), to_kind())) {
7329 SetChangesFlag(kElementsPointer);
7330 SetChangesFlag(kNewSpacePromotion);
7331 }
7332 set_representation(Representation::Tagged());
7333 }
7334
7335 class FromElementsKindField : public BitField<ElementsKind, 0, 5> {};
7336 class ToElementsKindField : public BitField<ElementsKind, 5, 5> {};
7337 class MapIsStableField : public BitField<bool, 10, 1> {};
7338
7339 Unique<Map> original_map_;
7340 Unique<Map> transitioned_map_;
7341 uint32_t bit_field_;
7342 };
7343
7344
7345 class HStringAdd final : public HBinaryOperation {
7346 public:
7347 static HInstruction* New(
7348 Isolate* isolate, Zone* zone, HValue* context, HValue* left,
7349 HValue* right, PretenureFlag pretenure_flag = NOT_TENURED,
7350 StringAddFlags flags = STRING_ADD_CHECK_BOTH,
7351 Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null());
7352
7353 StringAddFlags flags() const { return flags_; }
7354 PretenureFlag pretenure_flag() const { return pretenure_flag_; }
7355
7356 Representation RequiredInputRepresentation(int index) override {
7357 return Representation::Tagged();
7358 }
7359
7360 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
7361
7362 DECLARE_CONCRETE_INSTRUCTION(StringAdd)
7363
7364 protected:
7365 bool DataEquals(HValue* other) override {
7366 return flags_ == HStringAdd::cast(other)->flags_ &&
7367 pretenure_flag_ == HStringAdd::cast(other)->pretenure_flag_;
7368 }
7369
7370 private:
7371 HStringAdd(HValue* context, HValue* left, HValue* right,
7372 PretenureFlag pretenure_flag, StringAddFlags flags,
7373 Handle<AllocationSite> allocation_site)
7374 : HBinaryOperation(context, left, right, Strength::WEAK, HType::String()),
7375 flags_(flags),
7376 pretenure_flag_(pretenure_flag) {
7377 set_representation(Representation::Tagged());
7378 if ((flags & STRING_ADD_CONVERT) == STRING_ADD_CONVERT) {
7379 SetAllSideEffects();
7380 ClearFlag(kUseGVN);
7381 } else {
7382 SetChangesFlag(kNewSpacePromotion);
7383 SetFlag(kUseGVN);
7384 }
7385 SetDependsOnFlag(kMaps);
7386 if (FLAG_trace_pretenuring) {
7387 PrintF("HStringAdd with AllocationSite %p %s\n",
7388 allocation_site.is_null()
7389 ? static_cast<void*>(NULL)
7390 : static_cast<void*>(*allocation_site),
7391 pretenure_flag == TENURED ? "tenured" : "not tenured");
7392 }
7393 }
7394
7395 bool IsDeletable() const final {
7396 return (flags_ & STRING_ADD_CONVERT) != STRING_ADD_CONVERT;
7397 }
7398
7399 const StringAddFlags flags_;
7400 const PretenureFlag pretenure_flag_;
7401 };
7402
7403
7404 class HStringCharCodeAt final : public HTemplateInstruction<3> {
7405 public:
7406 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HStringCharCodeAt,
7407 HValue*,
7408 HValue*);
7409
7410 Representation RequiredInputRepresentation(int index) override {
7411 // The index is supposed to be Integer32.
7412 return index == 2
7413 ? Representation::Integer32()
7414 : Representation::Tagged();
7415 }
7416
7417 HValue* context() const { return OperandAt(0); }
7418 HValue* string() const { return OperandAt(1); }
7419 HValue* index() const { return OperandAt(2); }
7420
7421 DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
7422
7423 protected:
7424 bool DataEquals(HValue* other) override { return true; }
7425
7426 Range* InferRange(Zone* zone) override {
7427 return new(zone) Range(0, String::kMaxUtf16CodeUnit);
7428 }
7429
7430 private:
7431 HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
7432 SetOperandAt(0, context);
7433 SetOperandAt(1, string);
7434 SetOperandAt(2, index);
7435 set_representation(Representation::Integer32());
7436 SetFlag(kUseGVN);
7437 SetDependsOnFlag(kMaps);
7438 SetDependsOnFlag(kStringChars);
7439 SetChangesFlag(kNewSpacePromotion);
7440 }
7441
7442 // No side effects: runtime function assumes string + number inputs.
7443 bool IsDeletable() const override { return true; }
7444 };
7445
7446
7447 class HStringCharFromCode final : public HTemplateInstruction<2> {
7448 public:
7449 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
7450 HValue* char_code);
7451
7452 Representation RequiredInputRepresentation(int index) override {
7453 return index == 0
7454 ? Representation::Tagged()
7455 : Representation::Integer32();
7456 }
7457
7458 HValue* context() const { return OperandAt(0); }
7459 HValue* value() const { return OperandAt(1); }
7460
7461 bool DataEquals(HValue* other) override { return true; }
7462
7463 DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
7464
7465 private:
7466 HStringCharFromCode(HValue* context, HValue* char_code)
7467 : HTemplateInstruction<2>(HType::String()) {
7468 SetOperandAt(0, context);
7469 SetOperandAt(1, char_code);
7470 set_representation(Representation::Tagged());
7471 SetFlag(kUseGVN);
7472 SetChangesFlag(kNewSpacePromotion);
7473 }
7474
7475 bool IsDeletable() const override {
7476 return !value()->ToNumberCanBeObserved();
7477 }
7478 };
7479
7480
7481 template <int V>
7482 class HMaterializedLiteral : public HTemplateInstruction<V> {
7483 public:
7484 HMaterializedLiteral<V>(int index, int depth, AllocationSiteMode mode)
7485 : literal_index_(index), depth_(depth), allocation_site_mode_(mode) {
7486 this->set_representation(Representation::Tagged());
7487 }
7488
7489 HMaterializedLiteral<V>(int index, int depth)
7490 : literal_index_(index), depth_(depth),
7491 allocation_site_mode_(DONT_TRACK_ALLOCATION_SITE) {
7492 this->set_representation(Representation::Tagged());
7493 }
7494
7495 int literal_index() const { return literal_index_; }
7496 int depth() const { return depth_; }
7497 AllocationSiteMode allocation_site_mode() const {
7498 return allocation_site_mode_;
7499 }
7500
7501 private:
7502 bool IsDeletable() const final { return true; }
7503
7504 int literal_index_;
7505 int depth_;
7506 AllocationSiteMode allocation_site_mode_;
7507 };
7508
7509
7510 class HRegExpLiteral final : public HMaterializedLiteral<1> {
7511 public:
7512 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HRegExpLiteral,
7513 Handle<FixedArray>,
7514 Handle<String>,
7515 Handle<String>,
7516 int);
7517
7518 HValue* context() { return OperandAt(0); }
7519 Handle<FixedArray> literals() { return literals_; }
7520 Handle<String> pattern() { return pattern_; }
7521 Handle<String> flags() { return flags_; }
7522
7523 Representation RequiredInputRepresentation(int index) override {
7524 return Representation::Tagged();
7525 }
7526
7527 DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral)
7528
7529 private:
7530 HRegExpLiteral(HValue* context,
7531 Handle<FixedArray> literals,
7532 Handle<String> pattern,
7533 Handle<String> flags,
7534 int literal_index)
7535 : HMaterializedLiteral<1>(literal_index, 0),
7536 literals_(literals),
7537 pattern_(pattern),
7538 flags_(flags) {
7539 SetOperandAt(0, context);
7540 SetAllSideEffects();
7541 set_type(HType::JSObject());
7542 }
7543
7544 Handle<FixedArray> literals_;
7545 Handle<String> pattern_;
7546 Handle<String> flags_;
7547 };
7548
7549
7550 class HTypeof final : public HTemplateInstruction<2> {
7551 public:
7552 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HTypeof, HValue*);
7553
7554 HValue* context() const { return OperandAt(0); }
7555 HValue* value() const { return OperandAt(1); }
7556
7557 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
7558
7559 Representation RequiredInputRepresentation(int index) override {
7560 return Representation::Tagged();
7561 }
7562
7563 DECLARE_CONCRETE_INSTRUCTION(Typeof)
7564
7565 private:
7566 explicit HTypeof(HValue* context, HValue* value) {
7567 SetOperandAt(0, context);
7568 SetOperandAt(1, value);
7569 set_representation(Representation::Tagged());
7570 }
7571
7572 bool IsDeletable() const override { return true; }
7573 };
7574
7575
7576 class HTrapAllocationMemento final : public HTemplateInstruction<1> {
7577 public:
7578 DECLARE_INSTRUCTION_FACTORY_P1(HTrapAllocationMemento, HValue*);
7579
7580 Representation RequiredInputRepresentation(int index) override {
7581 return Representation::Tagged();
7582 }
7583
7584 HValue* object() { return OperandAt(0); }
7585
7586 DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento)
7587
7588 private:
7589 explicit HTrapAllocationMemento(HValue* obj) {
7590 SetOperandAt(0, obj);
7591 }
7592 };
7593
7594
7595 class HMaybeGrowElements final : public HTemplateInstruction<5> {
7596 public:
7597 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P6(HMaybeGrowElements, HValue*,
7598 HValue*, HValue*, HValue*, bool,
7599 ElementsKind);
7600
7601 Representation RequiredInputRepresentation(int index) override {
7602 if (index < 3) {
7603 return Representation::Tagged();
7604 }
7605 DCHECK(index == 3 || index == 4);
7606 return Representation::Integer32();
7607 }
7608
7609 HValue* context() const { return OperandAt(0); }
7610 HValue* object() const { return OperandAt(1); }
7611 HValue* elements() const { return OperandAt(2); }
7612 HValue* key() const { return OperandAt(3); }
7613 HValue* current_capacity() const { return OperandAt(4); }
7614
7615 bool is_js_array() const { return is_js_array_; }
7616 ElementsKind kind() const { return kind_; }
7617
7618 DECLARE_CONCRETE_INSTRUCTION(MaybeGrowElements)
7619
7620 protected:
7621 bool DataEquals(HValue* other) override { return true; }
7622
7623 private:
7624 explicit HMaybeGrowElements(HValue* context, HValue* object, HValue* elements,
7625 HValue* key, HValue* current_capacity,
7626 bool is_js_array, ElementsKind kind) {
7627 is_js_array_ = is_js_array;
7628 kind_ = kind;
7629
7630 SetOperandAt(0, context);
7631 SetOperandAt(1, object);
7632 SetOperandAt(2, elements);
7633 SetOperandAt(3, key);
7634 SetOperandAt(4, current_capacity);
7635
7636 SetFlag(kUseGVN);
7637 SetChangesFlag(kElementsPointer);
7638 SetChangesFlag(kNewSpacePromotion);
7639 set_representation(Representation::Tagged());
7640 }
7641
7642 bool is_js_array_;
7643 ElementsKind kind_;
7644 };
7645
7646
7647 class HToFastProperties final : public HUnaryOperation {
7648 public:
7649 DECLARE_INSTRUCTION_FACTORY_P1(HToFastProperties, HValue*);
7650
7651 Representation RequiredInputRepresentation(int index) override {
7652 return Representation::Tagged();
7653 }
7654
7655 DECLARE_CONCRETE_INSTRUCTION(ToFastProperties)
7656
7657 private:
7658 explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
7659 set_representation(Representation::Tagged());
7660 SetChangesFlag(kNewSpacePromotion);
7661
7662 // This instruction is not marked as kChangesMaps, but does
7663 // change the map of the input operand. Use it only when creating
7664 // object literals via a runtime call.
7665 DCHECK(value->IsCallRuntime());
7666 #ifdef DEBUG
7667 const Runtime::Function* function = HCallRuntime::cast(value)->function();
7668 DCHECK(function->function_id == Runtime::kCreateObjectLiteral);
7669 #endif
7670 }
7671
7672 bool IsDeletable() const override { return true; }
7673 };
7674
7675
7676 class HDateField final : public HUnaryOperation {
7677 public:
7678 DECLARE_INSTRUCTION_FACTORY_P2(HDateField, HValue*, Smi*);
7679
7680 Smi* index() const { return index_; }
7681
7682 Representation RequiredInputRepresentation(int index) override {
7683 return Representation::Tagged();
7684 }
7685
7686 DECLARE_CONCRETE_INSTRUCTION(DateField)
7687
7688 private:
7689 HDateField(HValue* date, Smi* index)
7690 : HUnaryOperation(date), index_(index) {
7691 set_representation(Representation::Tagged());
7692 }
7693
7694 Smi* index_;
7695 };
7696
7697
7698 class HSeqStringGetChar final : public HTemplateInstruction<2> {
7699 public:
7700 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
7701 String::Encoding encoding, HValue* string,
7702 HValue* index);
7703
7704 Representation RequiredInputRepresentation(int index) override {
7705 return (index == 0) ? Representation::Tagged()
7706 : Representation::Integer32();
7707 }
7708
7709 String::Encoding encoding() const { return encoding_; }
7710 HValue* string() const { return OperandAt(0); }
7711 HValue* index() const { return OperandAt(1); }
7712
7713 DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar)
7714
7715 protected:
7716 bool DataEquals(HValue* other) override {
7717 return encoding() == HSeqStringGetChar::cast(other)->encoding();
7718 }
7719
7720 Range* InferRange(Zone* zone) override {
7721 if (encoding() == String::ONE_BYTE_ENCODING) {
7722 return new(zone) Range(0, String::kMaxOneByteCharCode);
7723 } else {
7724 DCHECK_EQ(String::TWO_BYTE_ENCODING, encoding());
7725 return new(zone) Range(0, String::kMaxUtf16CodeUnit);
7726 }
7727 }
7728
7729 private:
7730 HSeqStringGetChar(String::Encoding encoding,
7731 HValue* string,
7732 HValue* index) : encoding_(encoding) {
7733 SetOperandAt(0, string);
7734 SetOperandAt(1, index);
7735 set_representation(Representation::Integer32());
7736 SetFlag(kUseGVN);
7737 SetDependsOnFlag(kStringChars);
7738 }
7739
7740 bool IsDeletable() const override { return true; }
7741
7742 String::Encoding encoding_;
7743 };
7744
7745
7746 class HSeqStringSetChar final : public HTemplateInstruction<4> {
7747 public:
7748 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(
7749 HSeqStringSetChar, String::Encoding,
7750 HValue*, HValue*, HValue*);
7751
7752 String::Encoding encoding() { return encoding_; }
7753 HValue* context() { return OperandAt(0); }
7754 HValue* string() { return OperandAt(1); }
7755 HValue* index() { return OperandAt(2); }
7756 HValue* value() { return OperandAt(3); }
7757
7758 Representation RequiredInputRepresentation(int index) override {
7759 return (index <= 1) ? Representation::Tagged()
7760 : Representation::Integer32();
7761 }
7762
7763 DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar)
7764
7765 private:
7766 HSeqStringSetChar(HValue* context,
7767 String::Encoding encoding,
7768 HValue* string,
7769 HValue* index,
7770 HValue* value) : encoding_(encoding) {
7771 SetOperandAt(0, context);
7772 SetOperandAt(1, string);
7773 SetOperandAt(2, index);
7774 SetOperandAt(3, value);
7775 set_representation(Representation::Tagged());
7776 SetChangesFlag(kStringChars);
7777 }
7778
7779 String::Encoding encoding_;
7780 };
7781
7782
7783 class HCheckMapValue final : public HTemplateInstruction<2> {
7784 public:
7785 DECLARE_INSTRUCTION_FACTORY_P2(HCheckMapValue, HValue*, HValue*);
7786
7787 Representation RequiredInputRepresentation(int index) override {
7788 return Representation::Tagged();
7789 }
7790
7791 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
7792
7793 HType CalculateInferredType() override {
7794 if (value()->type().IsHeapObject()) return value()->type();
7795 return HType::HeapObject();
7796 }
7797
7798 HValue* value() const { return OperandAt(0); }
7799 HValue* map() const { return OperandAt(1); }
7800
7801 HValue* Canonicalize() override;
7802
7803 DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
7804
7805 protected:
7806 int RedefinedOperandIndex() override { return 0; }
7807
7808 bool DataEquals(HValue* other) override { return true; }
7809
7810 private:
7811 HCheckMapValue(HValue* value, HValue* map)
7812 : HTemplateInstruction<2>(HType::HeapObject()) {
7813 SetOperandAt(0, value);
7814 SetOperandAt(1, map);
7815 set_representation(Representation::Tagged());
7816 SetFlag(kUseGVN);
7817 SetDependsOnFlag(kMaps);
7818 SetDependsOnFlag(kElementsKind);
7819 }
7820 };
7821
7822
7823 class HForInPrepareMap final : public HTemplateInstruction<2> {
7824 public:
7825 DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HForInPrepareMap, HValue*);
7826
7827 Representation RequiredInputRepresentation(int index) override {
7828 return Representation::Tagged();
7829 }
7830
7831 HValue* context() const { return OperandAt(0); }
7832 HValue* enumerable() const { return OperandAt(1); }
7833
7834 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
7835
7836 HType CalculateInferredType() override { return HType::Tagged(); }
7837
7838 DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
7839
7840 private:
7841 HForInPrepareMap(HValue* context,
7842 HValue* object) {
7843 SetOperandAt(0, context);
7844 SetOperandAt(1, object);
7845 set_representation(Representation::Tagged());
7846 SetAllSideEffects();
7847 }
7848 };
7849
7850
7851 class HForInCacheArray final : public HTemplateInstruction<2> {
7852 public:
7853 DECLARE_INSTRUCTION_FACTORY_P3(HForInCacheArray, HValue*, HValue*, int);
7854
7855 Representation RequiredInputRepresentation(int index) override {
7856 return Representation::Tagged();
7857 }
7858
7859 HValue* enumerable() const { return OperandAt(0); }
7860 HValue* map() const { return OperandAt(1); }
7861 int idx() const { return idx_; }
7862
7863 HForInCacheArray* index_cache() {
7864 return index_cache_;
7865 }
7866
7867 void set_index_cache(HForInCacheArray* index_cache) {
7868 index_cache_ = index_cache;
7869 }
7870
7871 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
7872
7873 HType CalculateInferredType() override { return HType::Tagged(); }
7874
7875 DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
7876
7877 private:
7878 HForInCacheArray(HValue* enumerable,
7879 HValue* keys,
7880 int idx) : idx_(idx) {
7881 SetOperandAt(0, enumerable);
7882 SetOperandAt(1, keys);
7883 set_representation(Representation::Tagged());
7884 }
7885
7886 int idx_;
7887 HForInCacheArray* index_cache_;
7888 };
7889
7890
7891 class HLoadFieldByIndex final : public HTemplateInstruction<2> {
7892 public:
7893 DECLARE_INSTRUCTION_FACTORY_P2(HLoadFieldByIndex, HValue*, HValue*);
7894
7895 HLoadFieldByIndex(HValue* object,
7896 HValue* index) {
7897 SetOperandAt(0, object);
7898 SetOperandAt(1, index);
7899 SetChangesFlag(kNewSpacePromotion);
7900 set_representation(Representation::Tagged());
7901 }
7902
7903 Representation RequiredInputRepresentation(int index) override {
7904 if (index == 1) {
7905 return Representation::Smi();
7906 } else {
7907 return Representation::Tagged();
7908 }
7909 }
7910
7911 HValue* object() const { return OperandAt(0); }
7912 HValue* index() const { return OperandAt(1); }
7913
7914 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
7915
7916 HType CalculateInferredType() override { return HType::Tagged(); }
7917
7918 DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
7919
7920 private:
7921 bool IsDeletable() const override { return true; }
7922 };
7923
7924
7925 class HStoreFrameContext: public HUnaryOperation {
7926 public:
7927 DECLARE_INSTRUCTION_FACTORY_P1(HStoreFrameContext, HValue*);
7928
7929 HValue* context() { return OperandAt(0); }
7930
7931 Representation RequiredInputRepresentation(int index) override {
7932 return Representation::Tagged();
7933 }
7934
7935 DECLARE_CONCRETE_INSTRUCTION(StoreFrameContext)
7936 private:
7937 explicit HStoreFrameContext(HValue* context)
7938 : HUnaryOperation(context) {
7939 set_representation(Representation::Tagged());
7940 SetChangesFlag(kContextSlots);
7941 }
7942 };
7943
7944
7945 class HAllocateBlockContext: public HTemplateInstruction<2> {
7946 public:
7947 DECLARE_INSTRUCTION_FACTORY_P3(HAllocateBlockContext, HValue*,
7948 HValue*, Handle<ScopeInfo>);
7949 HValue* context() const { return OperandAt(0); }
7950 HValue* function() const { return OperandAt(1); }
7951 Handle<ScopeInfo> scope_info() const { return scope_info_; }
7952
7953 Representation RequiredInputRepresentation(int index) override {
7954 return Representation::Tagged();
7955 }
7956
7957 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
7958
7959 DECLARE_CONCRETE_INSTRUCTION(AllocateBlockContext)
7960
7961 private:
7962 HAllocateBlockContext(HValue* context,
7963 HValue* function,
7964 Handle<ScopeInfo> scope_info)
7965 : scope_info_(scope_info) {
7966 SetOperandAt(0, context);
7967 SetOperandAt(1, function);
7968 set_representation(Representation::Tagged());
7969 }
7970
7971 Handle<ScopeInfo> scope_info_;
7972 };
7973
7974
7975
7976 #undef DECLARE_INSTRUCTION
7977 #undef DECLARE_CONCRETE_INSTRUCTION
7978
7979 } // namespace internal
7980 } // namespace v8
7981
7982 #endif // V8_HYDROGEN_INSTRUCTIONS_H_
OLDNEW
« no previous file with comments | « src/hydrogen-infer-types.cc ('k') | src/hydrogen-instructions.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698