Line data Source code
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_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_
6 : #define V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_
7 :
8 : #include <cstring>
9 : #include <iosfwd>
10 :
11 : #include "src/allocation.h"
12 : #include "src/ast/ast.h"
13 : #include "src/base/bits.h"
14 : #include "src/bit-vector.h"
15 : #include "src/conversions.h"
16 : #include "src/crankshaft/hydrogen-types.h"
17 : #include "src/crankshaft/unique.h"
18 : #include "src/deoptimizer.h"
19 : #include "src/globals.h"
20 : #include "src/interface-descriptors.h"
21 : #include "src/small-pointer-list.h"
22 : #include "src/utils.h"
23 : #include "src/zone/zone.h"
24 :
25 : namespace v8 {
26 : namespace internal {
27 :
28 : // Forward declarations.
29 : struct ChangesOf;
30 : class HBasicBlock;
31 : class HDiv;
32 : class HEnvironment;
33 : class HInferRepresentationPhase;
34 : class HInstruction;
35 : class HLoopInformation;
36 : class HStoreNamedField;
37 : class HValue;
38 : class LInstruction;
39 : class LChunkBuilder;
40 : class SmallMapList;
41 :
42 : #define HYDROGEN_ABSTRACT_INSTRUCTION_LIST(V) \
43 : V(ArithmeticBinaryOperation) \
44 : V(BinaryOperation) \
45 : V(BitwiseBinaryOperation) \
46 : V(ControlInstruction) \
47 : V(Instruction)
48 :
49 : #define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
50 : V(AbnormalExit) \
51 : V(AccessArgumentsAt) \
52 : V(Add) \
53 : V(Allocate) \
54 : V(ApplyArguments) \
55 : V(ArgumentsElements) \
56 : V(ArgumentsLength) \
57 : V(ArgumentsObject) \
58 : V(Bitwise) \
59 : V(BlockEntry) \
60 : V(BoundsCheck) \
61 : V(Branch) \
62 : V(CallWithDescriptor) \
63 : V(CallNewArray) \
64 : V(CallRuntime) \
65 : V(CapturedObject) \
66 : V(Change) \
67 : V(CheckArrayBufferNotNeutered) \
68 : V(CheckHeapObject) \
69 : V(CheckInstanceType) \
70 : V(CheckMaps) \
71 : V(CheckMapValue) \
72 : V(CheckSmi) \
73 : V(CheckValue) \
74 : V(ClampToUint8) \
75 : V(ClassOfTestAndBranch) \
76 : V(CompareNumericAndBranch) \
77 : V(CompareHoleAndBranch) \
78 : V(CompareGeneric) \
79 : V(CompareObjectEqAndBranch) \
80 : V(CompareMap) \
81 : V(Constant) \
82 : V(Context) \
83 : V(DebugBreak) \
84 : V(DeclareGlobals) \
85 : V(Deoptimize) \
86 : V(Div) \
87 : V(DummyUse) \
88 : V(EnterInlined) \
89 : V(EnvironmentMarker) \
90 : V(ForceRepresentation) \
91 : V(ForInCacheArray) \
92 : V(ForInPrepareMap) \
93 : V(Goto) \
94 : V(HasInstanceTypeAndBranch) \
95 : V(InnerAllocatedObject) \
96 : V(InvokeFunction) \
97 : V(HasInPrototypeChainAndBranch) \
98 : V(IsStringAndBranch) \
99 : V(IsSmiAndBranch) \
100 : V(IsUndetectableAndBranch) \
101 : V(LeaveInlined) \
102 : V(LoadContextSlot) \
103 : V(LoadFieldByIndex) \
104 : V(LoadFunctionPrototype) \
105 : V(LoadKeyed) \
106 : V(LoadNamedField) \
107 : V(LoadRoot) \
108 : V(MathFloorOfDiv) \
109 : V(MathMinMax) \
110 : V(MaybeGrowElements) \
111 : V(Mod) \
112 : V(Mul) \
113 : V(OsrEntry) \
114 : V(Parameter) \
115 : V(Power) \
116 : V(Prologue) \
117 : V(PushArguments) \
118 : V(Return) \
119 : V(Ror) \
120 : V(Sar) \
121 : V(SeqStringGetChar) \
122 : V(SeqStringSetChar) \
123 : V(Shl) \
124 : V(Shr) \
125 : V(Simulate) \
126 : V(StackCheck) \
127 : V(StoreCodeEntry) \
128 : V(StoreContextSlot) \
129 : V(StoreKeyed) \
130 : V(StoreNamedField) \
131 : V(StringAdd) \
132 : V(StringCharCodeAt) \
133 : V(StringCharFromCode) \
134 : V(StringCompareAndBranch) \
135 : V(Sub) \
136 : V(ThisFunction) \
137 : V(TransitionElementsKind) \
138 : V(TrapAllocationMemento) \
139 : V(Typeof) \
140 : V(TypeofIsAndBranch) \
141 : V(UnaryMathOperation) \
142 : V(UnknownOSRValue) \
143 : V(UseConst) \
144 : V(WrapReceiver)
145 :
146 : #define GVN_TRACKED_FLAG_LIST(V) \
147 : V(NewSpacePromotion)
148 :
149 : #define GVN_UNTRACKED_FLAG_LIST(V) \
150 : V(ArrayElements) \
151 : V(ArrayLengths) \
152 : V(StringLengths) \
153 : V(BackingStoreFields) \
154 : V(Calls) \
155 : V(ContextSlots) \
156 : V(DoubleArrayElements) \
157 : V(DoubleFields) \
158 : V(ElementsKind) \
159 : V(ElementsPointer) \
160 : V(GlobalVars) \
161 : V(InobjectFields) \
162 : V(Maps) \
163 : V(OsrEntries) \
164 : V(ExternalMemory) \
165 : V(StringChars) \
166 : V(TypedArrayElements)
167 :
168 :
169 : #define DECLARE_ABSTRACT_INSTRUCTION(type) \
170 : bool Is##type() const final { return true; } \
171 : static H##type* cast(HValue* value) { \
172 : DCHECK(value->Is##type()); \
173 : return reinterpret_cast<H##type*>(value); \
174 : }
175 :
176 :
177 : #define DECLARE_CONCRETE_INSTRUCTION(type) \
178 : LInstruction* CompileToLithium(LChunkBuilder* builder) final; \
179 : static H##type* cast(HValue* value) { \
180 : DCHECK(value->Is##type()); \
181 : return reinterpret_cast<H##type*>(value); \
182 : } \
183 : Opcode opcode() const final { return HValue::k##type; }
184 :
185 :
186 : enum PropertyAccessType { LOAD, STORE };
187 :
188 : Representation RepresentationFromMachineType(MachineType type);
189 :
190 : class Range final : public ZoneObject {
191 : public:
192 : Range()
193 : : lower_(kMinInt),
194 : upper_(kMaxInt),
195 : next_(NULL),
196 7856706 : can_be_minus_zero_(false) { }
197 :
198 : Range(int32_t lower, int32_t upper)
199 : : lower_(lower),
200 : upper_(upper),
201 : next_(NULL),
202 3639836 : can_be_minus_zero_(false) { }
203 :
204 : int32_t upper() const { return upper_; }
205 : int32_t lower() const { return lower_; }
206 : Range* next() const { return next_; }
207 : Range* CopyClearLower(Zone* zone) const {
208 149278 : return new(zone) Range(kMinInt, upper_);
209 : }
210 : Range* CopyClearUpper(Zone* zone) const {
211 149278 : return new(zone) Range(lower_, kMaxInt);
212 : }
213 748872 : Range* Copy(Zone* zone) const {
214 748874 : Range* result = new(zone) Range(lower_, upper_);
215 : result->set_can_be_minus_zero(CanBeMinusZero());
216 748874 : return result;
217 : }
218 : int32_t Mask() const;
219 9103544 : void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
220 2889321 : bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
221 1711810 : bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
222 : bool CanBeNegative() const { return lower_ < 0; }
223 : bool CanBePositive() const { return upper_ > 0; }
224 18790 : bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
225 : bool IsMostGeneric() const {
226 530758 : return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
227 : }
228 : bool IsInSmiRange() const {
229 : return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
230 : }
231 : void ClampToSmi() {
232 : lower_ = Max(lower_, Smi::kMinValue);
233 114828 : upper_ = Min(upper_, Smi::kMaxValue);
234 : }
235 : void Clear();
236 : void KeepOrder();
237 : #ifdef DEBUG
238 : void Verify() const;
239 : #endif
240 :
241 : void StackUpon(Range* other) {
242 438859 : Intersect(other);
243 438859 : next_ = other;
244 : }
245 :
246 : void Intersect(Range* other);
247 : void Union(Range* other);
248 : void CombinedMax(Range* other);
249 : void CombinedMin(Range* other);
250 :
251 : void AddConstant(int32_t value);
252 : void Sar(int32_t value);
253 : void Shl(int32_t value);
254 : bool AddAndCheckOverflow(const Representation& r, Range* other);
255 : bool SubAndCheckOverflow(const Representation& r, Range* other);
256 : bool MulAndCheckOverflow(const Representation& r, Range* other);
257 :
258 : private:
259 : int32_t lower_;
260 : int32_t upper_;
261 : Range* next_;
262 : bool can_be_minus_zero_;
263 : };
264 :
265 :
266 : class HUseListNode: public ZoneObject {
267 : public:
268 : HUseListNode(HValue* value, int index, HUseListNode* tail)
269 24165101 : : tail_(tail), value_(value), index_(index) {
270 : }
271 :
272 : HUseListNode* tail();
273 : HValue* value() const { return value_; }
274 : int index() const { return index_; }
275 :
276 9528944 : void set_tail(HUseListNode* list) { tail_ = list; }
277 :
278 : #ifdef DEBUG
279 : void Zap() {
280 : tail_ = reinterpret_cast<HUseListNode*>(1);
281 : value_ = NULL;
282 : index_ = -1;
283 : }
284 : #endif
285 :
286 : private:
287 : HUseListNode* tail_;
288 : HValue* value_;
289 : int index_;
290 : };
291 :
292 :
293 : // We reuse use list nodes behind the scenes as uses are added and deleted.
294 : // This class is the safe way to iterate uses while deleting them.
295 : class HUseIterator final BASE_EMBEDDED {
296 : public:
297 10949 : bool Done() { return current_ == NULL; }
298 : void Advance();
299 :
300 7446 : HValue* value() {
301 : DCHECK(!Done());
302 7446 : return value_;
303 : }
304 :
305 : int index() {
306 : DCHECK(!Done());
307 : return index_;
308 : }
309 :
310 : private:
311 : explicit HUseIterator(HUseListNode* head);
312 :
313 : HUseListNode* current_;
314 : HUseListNode* next_;
315 : HValue* value_;
316 : int index_;
317 :
318 : friend class HValue;
319 : };
320 :
321 :
322 : // All tracked flags should appear before untracked ones.
323 : enum GVNFlag {
324 : // Declare global value numbering flags.
325 : #define DECLARE_FLAG(Type) k##Type,
326 : GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
327 : GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
328 : #undef DECLARE_FLAG
329 : #define COUNT_FLAG(Type) + 1
330 : kNumberOfTrackedSideEffects = 0 GVN_TRACKED_FLAG_LIST(COUNT_FLAG),
331 : kNumberOfUntrackedSideEffects = 0 GVN_UNTRACKED_FLAG_LIST(COUNT_FLAG),
332 : #undef COUNT_FLAG
333 : kNumberOfFlags = kNumberOfTrackedSideEffects + kNumberOfUntrackedSideEffects
334 : };
335 :
336 :
337 : static inline GVNFlag GVNFlagFromInt(int i) {
338 : DCHECK(i >= 0);
339 : DCHECK(i < kNumberOfFlags);
340 293087 : return static_cast<GVNFlag>(i);
341 : }
342 :
343 :
344 : class DecompositionResult final BASE_EMBEDDED {
345 : public:
346 : DecompositionResult() : base_(NULL), offset_(0), scale_(0) {}
347 :
348 : HValue* base() { return base_; }
349 : int offset() { return offset_; }
350 : int scale() { return scale_; }
351 :
352 : bool Apply(HValue* other_base, int other_offset, int other_scale = 0) {
353 : if (base_ == NULL) {
354 : base_ = other_base;
355 : offset_ = other_offset;
356 : scale_ = other_scale;
357 : return true;
358 : } else {
359 : if (scale_ == 0) {
360 : base_ = other_base;
361 : offset_ += other_offset;
362 : scale_ = other_scale;
363 : return true;
364 : } else {
365 : return false;
366 : }
367 : }
368 : }
369 :
370 : void SwapValues(HValue** other_base, int* other_offset, int* other_scale) {
371 : swap(&base_, other_base);
372 : swap(&offset_, other_offset);
373 : swap(&scale_, other_scale);
374 : }
375 :
376 : private:
377 : template <class T> void swap(T* a, T* b) {
378 : T c(*a);
379 : *a = *b;
380 : *b = c;
381 : }
382 :
383 : HValue* base_;
384 : int offset_;
385 : int scale_;
386 : };
387 :
388 :
389 : typedef EnumSet<GVNFlag, int32_t> GVNFlagSet;
390 :
391 :
392 : class HValue : public ZoneObject {
393 : public:
394 : static const int kNoNumber = -1;
395 :
396 : enum Flag {
397 : kFlexibleRepresentation,
398 : kCannotBeTagged,
399 : // Participate in Global Value Numbering, i.e. elimination of
400 : // unnecessary recomputations. If an instruction sets this flag, it must
401 : // implement DataEquals(), which will be used to determine if other
402 : // occurrences of the instruction are indeed the same.
403 : kUseGVN,
404 : // Track instructions that are dominating side effects. If an instruction
405 : // sets this flag, it must implement HandleSideEffectDominator() and should
406 : // indicate which side effects to track by setting GVN flags.
407 : kTrackSideEffectDominators,
408 : kCanOverflow,
409 : kBailoutOnMinusZero,
410 : kCanBeDivByZero,
411 : kLeftCanBeMinInt,
412 : kLeftCanBeNegative,
413 : kLeftCanBePositive,
414 : kTruncatingToNumber,
415 : kIsArguments,
416 : kTruncatingToInt32,
417 : kAllUsesTruncatingToInt32,
418 : kTruncatingToSmi,
419 : kAllUsesTruncatingToSmi,
420 : // Set after an instruction is killed.
421 : kIsDead,
422 : // Instructions that are allowed to produce full range unsigned integer
423 : // values are marked with kUint32 flag. If arithmetic shift or a load from
424 : // EXTERNAL_UINT32_ELEMENTS array is not marked with this flag
425 : // it will deoptimize if result does not fit into signed integer range.
426 : // HGraph::ComputeSafeUint32Operations is responsible for setting this
427 : // flag.
428 : kUint32,
429 : kHasNoObservableSideEffects,
430 : // Indicates an instruction shouldn't be replaced by optimization, this flag
431 : // is useful to set in cases where recomputing a value is cheaper than
432 : // extending the value's live range and spilling it.
433 : kCantBeReplaced,
434 : // Indicates the instruction is live during dead code elimination.
435 : kIsLive,
436 :
437 : // HEnvironmentMarkers are deleted before dead code
438 : // elimination takes place, so they can repurpose the kIsLive flag:
439 : kEndsLiveRange = kIsLive,
440 :
441 : // TODO(everyone): Don't forget to update this!
442 : kLastFlag = kIsLive
443 : };
444 :
445 : STATIC_ASSERT(kLastFlag < kBitsPerInt);
446 :
447 : static HValue* cast(HValue* value) { return value; }
448 :
449 : enum Opcode {
450 : // Declare a unique enum value for each hydrogen instruction.
451 : #define DECLARE_OPCODE(type) k##type,
452 : HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
453 : kPhi
454 : #undef DECLARE_OPCODE
455 : };
456 : virtual Opcode opcode() const = 0;
457 :
458 : // Declare a non-virtual predicates for each concrete HInstruction or HValue.
459 : #define DECLARE_PREDICATE(type) \
460 : bool Is##type() const { return opcode() == k##type; }
461 527604391 : HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
462 : #undef DECLARE_PREDICATE
463 18613200 : bool IsPhi() const { return opcode() == kPhi; }
464 :
465 : // Declare virtual predicates for abstract HInstruction or HValue
466 : #define DECLARE_PREDICATE(type) \
467 : virtual bool Is##type() const { return false; }
468 71278816 : HYDROGEN_ABSTRACT_INSTRUCTION_LIST(DECLARE_PREDICATE)
469 : #undef DECLARE_PREDICATE
470 :
471 : bool IsBitwiseBinaryShift() {
472 : return IsShl() || IsShr() || IsSar();
473 : }
474 :
475 : explicit HValue(HType type = HType::Tagged())
476 : : block_(NULL),
477 : id_(kNoNumber),
478 : type_(type),
479 : use_list_(NULL),
480 : range_(NULL),
481 : #ifdef DEBUG
482 : range_poisoned_(false),
483 : #endif
484 66373426 : flags_(0) {}
485 0 : virtual ~HValue() {}
486 :
487 0 : virtual SourcePosition position() const { return SourcePosition::Unknown(); }
488 :
489 : HBasicBlock* block() const { return block_; }
490 : void SetBlock(HBasicBlock* block);
491 :
492 : // Note: Never call this method for an unlinked value.
493 : Isolate* isolate() const;
494 :
495 : int id() const { return id_; }
496 : void set_id(int id) { id_ = id; }
497 :
498 13247756 : HUseIterator uses() const { return HUseIterator(use_list_); }
499 :
500 49094980 : virtual bool EmitAtUses() { return false; }
501 :
502 : Representation representation() const { return representation_; }
503 : void ChangeRepresentation(Representation r) {
504 : DCHECK(CheckFlag(kFlexibleRepresentation));
505 : DCHECK(!CheckFlag(kCannotBeTagged) || !r.IsTagged());
506 1402140 : RepresentationChanged(r);
507 1402145 : representation_ = r;
508 1399814 : if (r.IsTagged()) {
509 : // Tagged is the bottom of the lattice, don't go any further.
510 : ClearFlag(kFlexibleRepresentation);
511 : }
512 : }
513 : virtual void AssumeRepresentation(Representation r);
514 :
515 1362103 : virtual Representation KnownOptimalRepresentation() {
516 : Representation r = representation();
517 1362103 : if (r.IsTagged()) {
518 : HType t = type();
519 150802 : if (t.IsSmi()) return Representation::Smi();
520 150802 : if (t.IsHeapNumber()) return Representation::Double();
521 150802 : if (t.IsHeapObject()) return r;
522 : return Representation::None();
523 : }
524 1211301 : return r;
525 : }
526 :
527 : HType type() const { return type_; }
528 : void set_type(HType new_type) {
529 : DCHECK(new_type.IsSubtypeOf(type_));
530 4087262 : type_ = new_type;
531 : }
532 :
533 : // There are HInstructions that do not really change a value, they
534 : // only add pieces of information to it (like bounds checks, map checks,
535 : // smi checks...).
536 : // We call these instructions "informative definitions", or "iDef".
537 : // One of the iDef operands is special because it is the value that is
538 : // "transferred" to the output, we call it the "redefined operand".
539 : // If an HValue is an iDef it must override RedefinedOperandIndex() so that
540 : // it does not return kNoRedefinedOperand;
541 : static const int kNoRedefinedOperand = -1;
542 27273961 : virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; }
543 : bool IsInformativeDefinition() {
544 : return RedefinedOperandIndex() != kNoRedefinedOperand;
545 : }
546 0 : HValue* RedefinedOperand() {
547 0 : int index = RedefinedOperandIndex();
548 0 : return index == kNoRedefinedOperand ? NULL : OperandAt(index);
549 : }
550 :
551 : bool CanReplaceWithDummyUses();
552 :
553 21934896 : virtual int argument_delta() const { return 0; }
554 :
555 : // A purely informative definition is an idef that will not emit code and
556 : // should therefore be removed from the graph in the RestoreActualValues
557 : // phase (so that live ranges will be shorter).
558 281128 : virtual bool IsPurelyInformativeDefinition() { return false; }
559 :
560 : // This method must always return the original HValue SSA definition,
561 : // regardless of any chain of iDefs of this value.
562 27257773 : HValue* ActualValue() {
563 : HValue* value = this;
564 : int index;
565 55430099 : while ((index = value->RedefinedOperandIndex()) != kNoRedefinedOperand) {
566 914553 : value = value->OperandAt(index);
567 : }
568 27257765 : return value;
569 : }
570 :
571 : bool IsInteger32Constant();
572 : int32_t GetInteger32Constant();
573 : bool EqualsInteger32Constant(int32_t value);
574 :
575 : bool IsDefinedAfter(HBasicBlock* other) const;
576 :
577 : // Operands.
578 : virtual int OperandCount() const = 0;
579 : virtual HValue* OperandAt(int index) const = 0;
580 : void SetOperandAt(int index, HValue* value);
581 :
582 : void DeleteAndReplaceWith(HValue* other);
583 : void ReplaceAllUsesWith(HValue* other);
584 : bool HasNoUses() const { return use_list_ == NULL; }
585 3341 : bool HasOneUse() const {
586 206934 : return use_list_ != NULL && use_list_->tail() == NULL;
587 : }
588 : bool HasMultipleUses() const {
589 : return use_list_ != NULL && use_list_->tail() != NULL;
590 : }
591 : int UseCount() const;
592 :
593 : // Mark this HValue as dead and to be removed from other HValues' use lists.
594 : void Kill();
595 :
596 : int flags() const { return flags_; }
597 24370669 : void SetFlag(Flag f) { flags_ |= (1 << f); }
598 4099497 : void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
599 257529040 : bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
600 15062 : void CopyFlag(Flag f, HValue* other) {
601 15062 : if (other->CheckFlag(f)) SetFlag(f);
602 : }
603 :
604 : // Returns true if the flag specified is set for all uses, false otherwise.
605 : bool CheckUsesForFlag(Flag f) const;
606 : // Same as before and the first one without the flag is returned in value.
607 : bool CheckUsesForFlag(Flag f, HValue** value) const;
608 : // Returns true if the flag specified is set for all uses, and this set
609 : // of uses is non-empty.
610 : bool HasAtLeastOneUseWithFlagAndNoneWithout(Flag f) const;
611 :
612 : GVNFlagSet ChangesFlags() const { return changes_flags_; }
613 : GVNFlagSet DependsOnFlags() const { return depends_on_flags_; }
614 : void SetChangesFlag(GVNFlag f) { changes_flags_.Add(f); }
615 : void SetDependsOnFlag(GVNFlag f) { depends_on_flags_.Add(f); }
616 : void ClearChangesFlag(GVNFlag f) { changes_flags_.Remove(f); }
617 : void ClearDependsOnFlag(GVNFlag f) { depends_on_flags_.Remove(f); }
618 : bool CheckChangesFlag(GVNFlag f) const {
619 : return changes_flags_.Contains(f);
620 : }
621 : bool CheckDependsOnFlag(GVNFlag f) const {
622 : return depends_on_flags_.Contains(f);
623 : }
624 : void SetAllSideEffects() { changes_flags_.Add(AllSideEffectsFlagSet()); }
625 : void ClearAllSideEffects() {
626 : changes_flags_.Remove(AllSideEffectsFlagSet());
627 : }
628 : bool HasSideEffects() const {
629 : return changes_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
630 : }
631 34586136 : bool HasObservableSideEffects() const {
632 67824187 : return !CheckFlag(kHasNoObservableSideEffects) &&
633 : changes_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
634 : }
635 :
636 : GVNFlagSet SideEffectFlags() const {
637 : GVNFlagSet result = ChangesFlags();
638 : result.Intersect(AllSideEffectsFlagSet());
639 : return result;
640 : }
641 :
642 : GVNFlagSet ObservableChangesFlags() const {
643 : GVNFlagSet result = ChangesFlags();
644 : result.Intersect(AllObservableSideEffectsFlagSet());
645 : return result;
646 : }
647 :
648 : Range* range() const {
649 : DCHECK(!range_poisoned_);
650 : return range_;
651 : }
652 : bool HasRange() const {
653 : DCHECK(!range_poisoned_);
654 : return range_ != NULL;
655 : }
656 : #ifdef DEBUG
657 : void PoisonRange() { range_poisoned_ = true; }
658 : #endif
659 : void AddNewRange(Range* r, Zone* zone);
660 : void RemoveLastAddedRange();
661 : void ComputeInitialRange(Zone* zone);
662 :
663 : // Escape analysis helpers.
664 11574 : virtual bool HasEscapingOperandAt(int index) { return true; }
665 9623 : virtual bool HasOutOfBoundsAccess(int size) { return false; }
666 :
667 : // Representation helpers.
668 1856531 : virtual Representation observed_input_representation(int index) {
669 1856531 : return Representation::None();
670 : }
671 : virtual Representation RequiredInputRepresentation(int index) = 0;
672 : virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
673 :
674 : // This gives the instruction an opportunity to replace itself with an
675 : // instruction that does the same in some better way. To replace an
676 : // instruction with a new one, first add the new instruction to the graph,
677 : // then return it. Return NULL to have the instruction deleted.
678 26183780 : virtual HValue* Canonicalize() { return this; }
679 :
680 : bool Equals(HValue* other);
681 : virtual intptr_t Hashcode();
682 :
683 : // Compute unique ids upfront that is safe wrt GC and concurrent compilation.
684 22305245 : virtual void FinalizeUniqueness() { }
685 :
686 : // Printing support.
687 : virtual std::ostream& PrintTo(std::ostream& os) const = 0; // NOLINT
688 :
689 : const char* Mnemonic() const;
690 :
691 : // Type information helpers.
692 : bool HasMonomorphicJSObjectType();
693 :
694 : // TODO(mstarzinger): For now instructions can override this function to
695 : // specify statically known types, once HType can convey more information
696 : // it should be based on the HType.
697 627741 : virtual Handle<Map> GetMonomorphicJSObjectMap() { return Handle<Map>(); }
698 :
699 : // Updated the inferred type of this instruction and returns true if
700 : // it has changed.
701 : bool UpdateInferredType();
702 :
703 : virtual HType CalculateInferredType();
704 :
705 : // This function must be overridden for instructions which have the
706 : // kTrackSideEffectDominators flag set, to track instructions that are
707 : // dominating side effects.
708 : // It returns true if it removed an instruction which had side effects.
709 0 : virtual bool HandleSideEffectDominator(GVNFlag side_effect,
710 : HValue* dominator) {
711 0 : UNREACHABLE();
712 : return false;
713 : }
714 :
715 : // Check if this instruction has some reason that prevents elimination.
716 19994 : bool CannotBeEliminated() const {
717 19994 : return HasObservableSideEffects() || !IsDeletable();
718 : }
719 :
720 : #ifdef DEBUG
721 : virtual void Verify() = 0;
722 : #endif
723 :
724 : // Returns true conservatively if the program might be able to observe a
725 : // ToString() operation on this value.
726 : bool ToStringCanBeObserved() const {
727 : return ToStringOrToNumberCanBeObserved();
728 : }
729 :
730 : // Returns true conservatively if the program might be able to observe a
731 : // ToNumber() operation on this value.
732 : bool ToNumberCanBeObserved() const {
733 99829 : return ToStringOrToNumberCanBeObserved();
734 : }
735 :
736 53266 : MinusZeroMode GetMinusZeroMode() {
737 : return CheckFlag(kBailoutOnMinusZero)
738 55196 : ? FAIL_ON_MINUS_ZERO : TREAT_MINUS_ZERO_AS_ZERO;
739 : }
740 :
741 : protected:
742 : // This function must be overridden for instructions with flag kUseGVN, to
743 : // compare the non-Operand parts of the instruction.
744 0 : virtual bool DataEquals(HValue* other) {
745 0 : UNREACHABLE();
746 : return false;
747 : }
748 :
749 99829 : bool ToStringOrToNumberCanBeObserved() const {
750 99829 : if (type().IsTaggedPrimitive()) return false;
751 47903 : if (type().IsJSReceiver()) return true;
752 47625 : return !representation().IsSmiOrInteger32() && !representation().IsDouble();
753 : }
754 :
755 81459 : virtual Representation RepresentationFromInputs() {
756 81459 : return representation();
757 : }
758 : virtual Representation RepresentationFromUses();
759 : Representation RepresentationFromUseRequirements();
760 : bool HasNonSmiUse();
761 : virtual void UpdateRepresentation(Representation new_rep,
762 : HInferRepresentationPhase* h_infer,
763 : const char* reason);
764 : void AddDependantsToWorklist(HInferRepresentationPhase* h_infer);
765 :
766 776967 : virtual void RepresentationChanged(Representation to) { }
767 :
768 : virtual Range* InferRange(Zone* zone);
769 : virtual void DeleteFromGraph() = 0;
770 : virtual void InternalSetOperandAt(int index, HValue* value) = 0;
771 : void clear_block() {
772 : DCHECK(block_ != NULL);
773 7690492 : block_ = NULL;
774 : }
775 :
776 : void set_representation(Representation r) {
777 : DCHECK(representation_.IsNone() && !r.IsNone());
778 14635219 : representation_ = r;
779 : }
780 :
781 : static GVNFlagSet AllFlagSet() {
782 : GVNFlagSet result;
783 : #define ADD_FLAG(Type) result.Add(k##Type);
784 : GVN_TRACKED_FLAG_LIST(ADD_FLAG)
785 : GVN_UNTRACKED_FLAG_LIST(ADD_FLAG)
786 : #undef ADD_FLAG
787 : return result;
788 : }
789 :
790 : // A flag mask to mark an instruction as having arbitrary side effects.
791 : static GVNFlagSet AllSideEffectsFlagSet() {
792 : GVNFlagSet result = AllFlagSet();
793 : result.Remove(kOsrEntries);
794 : return result;
795 : }
796 : friend std::ostream& operator<<(std::ostream& os, const ChangesOf& v);
797 :
798 : // A flag mask of all side effects that can make observable changes in
799 : // an executing program (i.e. are not safe to repeat, move or remove);
800 : static GVNFlagSet AllObservableSideEffectsFlagSet() {
801 : GVNFlagSet result = AllFlagSet();
802 : result.Remove(kNewSpacePromotion);
803 : result.Remove(kElementsKind);
804 : result.Remove(kElementsPointer);
805 : result.Remove(kMaps);
806 : return result;
807 : }
808 :
809 : // Remove the matching use from the use list if present. Returns the
810 : // removed list node or NULL.
811 : HUseListNode* RemoveUse(HValue* value, int index);
812 :
813 : void RegisterUse(int index, HValue* new_value);
814 :
815 : HBasicBlock* block_;
816 :
817 : // The id of this instruction in the hydrogen graph, assigned when first
818 : // added to the graph. Reflects creation order.
819 : int id_;
820 :
821 : Representation representation_;
822 : HType type_;
823 : HUseListNode* use_list_;
824 : Range* range_;
825 : #ifdef DEBUG
826 : bool range_poisoned_;
827 : #endif
828 : int flags_;
829 : GVNFlagSet changes_flags_;
830 : GVNFlagSet depends_on_flags_;
831 :
832 : private:
833 13038 : virtual bool IsDeletable() const { return false; }
834 :
835 : DISALLOW_COPY_AND_ASSIGN(HValue);
836 : };
837 :
838 : // Support for printing various aspects of an HValue.
839 : struct NameOf {
840 0 : explicit NameOf(const HValue* const v) : value(v) {}
841 : const HValue* value;
842 : };
843 :
844 :
845 : struct TypeOf {
846 0 : explicit TypeOf(const HValue* const v) : value(v) {}
847 : const HValue* value;
848 : };
849 :
850 :
851 : struct ChangesOf {
852 0 : explicit ChangesOf(const HValue* const v) : value(v) {}
853 : const HValue* value;
854 : };
855 :
856 :
857 : std::ostream& operator<<(std::ostream& os, const HValue& v);
858 : std::ostream& operator<<(std::ostream& os, const NameOf& v);
859 : std::ostream& operator<<(std::ostream& os, const TypeOf& v);
860 : std::ostream& operator<<(std::ostream& os, const ChangesOf& v);
861 :
862 :
863 : #define DECLARE_INSTRUCTION_FACTORY_P0(I) \
864 : static I* New(Isolate* isolate, Zone* zone, HValue* context) { \
865 : return new (zone) I(); \
866 : }
867 :
868 : #define DECLARE_INSTRUCTION_FACTORY_P1(I, P1) \
869 : static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1) { \
870 : return new (zone) I(p1); \
871 : }
872 :
873 : #define DECLARE_INSTRUCTION_FACTORY_P2(I, P1, P2) \
874 : static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2) { \
875 : return new (zone) I(p1, p2); \
876 : }
877 :
878 : #define DECLARE_INSTRUCTION_FACTORY_P3(I, P1, P2, P3) \
879 : static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
880 : P3 p3) { \
881 : return new (zone) I(p1, p2, p3); \
882 : }
883 :
884 : #define DECLARE_INSTRUCTION_FACTORY_P4(I, P1, P2, P3, P4) \
885 : static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
886 : P3 p3, P4 p4) { \
887 : return new (zone) I(p1, p2, p3, p4); \
888 : }
889 :
890 : #define DECLARE_INSTRUCTION_FACTORY_P5(I, P1, P2, P3, P4, P5) \
891 : static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
892 : P3 p3, P4 p4, P5 p5) { \
893 : return new (zone) I(p1, p2, p3, p4, p5); \
894 : }
895 :
896 : #define DECLARE_INSTRUCTION_FACTORY_P6(I, P1, P2, P3, P4, P5, P6) \
897 : static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
898 : P3 p3, P4 p4, P5 p5, P6 p6) { \
899 : return new (zone) I(p1, p2, p3, p4, p5, p6); \
900 : }
901 :
902 : #define DECLARE_INSTRUCTION_FACTORY_P7(I, P1, P2, P3, P4, P5, P6, P7) \
903 : static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
904 : P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) { \
905 : return new (zone) I(p1, p2, p3, p4, p5, p6, p7); \
906 : }
907 :
908 : #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P0(I) \
909 : static I* New(Isolate* isolate, Zone* zone, HValue* context) { \
910 : return new (zone) I(context); \
911 : }
912 :
913 : #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(I, P1) \
914 : static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1) { \
915 : return new (zone) I(context, p1); \
916 : }
917 :
918 : #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(I, P1, P2) \
919 : static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2) { \
920 : return new (zone) I(context, p1, p2); \
921 : }
922 :
923 : #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(I, P1, P2, P3) \
924 : static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
925 : P3 p3) { \
926 : return new (zone) I(context, p1, p2, p3); \
927 : }
928 :
929 : #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(I, P1, P2, P3, P4) \
930 : static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
931 : P3 p3, P4 p4) { \
932 : return new (zone) I(context, p1, p2, p3, p4); \
933 : }
934 :
935 : #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(I, P1, P2, P3, P4, P5) \
936 : static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
937 : P3 p3, P4 p4, P5 p5) { \
938 : return new (zone) I(context, p1, p2, p3, p4, p5); \
939 : }
940 :
941 : #define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P6(I, P1, P2, P3, P4, P5, P6) \
942 : static I* New(Isolate* isolate, Zone* zone, HValue* context, P1 p1, P2 p2, \
943 : P3 p3, P4 p4, P5 p5, P6 p6) { \
944 : return new (zone) I(context, p1, p2, p3, p4, p5, p6); \
945 : }
946 :
947 0 : class HInstruction : public HValue {
948 : public:
949 : HInstruction* next() const { return next_; }
950 : HInstruction* previous() const { return previous_; }
951 :
952 : std::ostream& PrintTo(std::ostream& os) const override; // NOLINT
953 : virtual std::ostream& PrintDataTo(std::ostream& os) const; // NOLINT
954 :
955 40696258 : bool IsLinked() const { return block() != NULL; }
956 : void Unlink();
957 :
958 : void InsertBefore(HInstruction* next);
959 :
960 : template<class T> T* Prepend(T* instr) {
961 11101 : instr->InsertBefore(this);
962 : return instr;
963 : }
964 :
965 : void InsertAfter(HInstruction* previous);
966 :
967 : template<class T> T* Append(T* instr) {
968 0 : instr->InsertAfter(this);
969 : return instr;
970 : }
971 :
972 : // The position is a write-once variable.
973 53415633 : SourcePosition position() const override { return position_; }
974 : bool has_position() const { return position_.IsKnown(); }
975 : void set_position(SourcePosition position) {
976 : DCHECK(position.IsKnown());
977 24328091 : position_ = position;
978 : }
979 :
980 : bool Dominates(HInstruction* other);
981 0 : bool CanTruncateToSmi() const { return CheckFlag(kTruncatingToSmi); }
982 182720 : bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); }
983 52946 : bool CanTruncateToNumber() const { return CheckFlag(kTruncatingToNumber); }
984 :
985 : virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
986 :
987 : #ifdef DEBUG
988 : void Verify() override;
989 : #endif
990 :
991 : bool CanDeoptimize();
992 :
993 1731955 : virtual bool HasStackCheck() { return false; }
994 :
995 96342 : DECLARE_ABSTRACT_INSTRUCTION(Instruction)
996 :
997 : protected:
998 : explicit HInstruction(HType type = HType::Tagged())
999 : : HValue(type),
1000 : next_(NULL),
1001 : previous_(NULL),
1002 32490157 : position_(SourcePosition::Unknown()) {
1003 : SetDependsOnFlag(kOsrEntries);
1004 : }
1005 :
1006 6726099 : void DeleteFromGraph() override { Unlink(); }
1007 :
1008 : private:
1009 : void InitializeAsFirst(HBasicBlock* block) {
1010 : DCHECK(!IsLinked());
1011 4620854 : SetBlock(block);
1012 : }
1013 :
1014 : HInstruction* next_;
1015 : HInstruction* previous_;
1016 : SourcePosition position_;
1017 :
1018 : friend class HBasicBlock;
1019 : };
1020 :
1021 :
1022 : template<int V>
1023 0 : class HTemplateInstruction : public HInstruction {
1024 : public:
1025 44306591 : int OperandCount() const final { return V; }
1026 48596619 : HValue* OperandAt(int i) const final { return inputs_[i]; }
1027 :
1028 : protected:
1029 : explicit HTemplateInstruction(HType type = HType::Tagged())
1030 20835952 : : HInstruction(type) {}
1031 :
1032 11070455 : void InternalSetOperandAt(int i, HValue* value) final { inputs_[i] = value; }
1033 :
1034 : private:
1035 : EmbeddedContainer<HValue*, V> inputs_;
1036 : };
1037 :
1038 :
1039 4617298 : class HControlInstruction : public HInstruction {
1040 : public:
1041 : virtual HBasicBlock* SuccessorAt(int i) const = 0;
1042 : virtual int SuccessorCount() const = 0;
1043 : virtual void SetSuccessorAt(int i, HBasicBlock* block) = 0;
1044 :
1045 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1046 :
1047 586739 : virtual bool KnownSuccessorBlock(HBasicBlock** block) {
1048 586739 : *block = NULL;
1049 586739 : return false;
1050 : }
1051 :
1052 9628907 : HBasicBlock* FirstSuccessor() {
1053 9628907 : return SuccessorCount() > 0 ? SuccessorAt(0) : NULL;
1054 : }
1055 5560236 : HBasicBlock* SecondSuccessor() {
1056 5560236 : return SuccessorCount() > 1 ? SuccessorAt(1) : NULL;
1057 : }
1058 :
1059 1787 : void Not() {
1060 1787 : HBasicBlock* swap = SuccessorAt(0);
1061 1787 : SetSuccessorAt(0, SuccessorAt(1));
1062 1787 : SetSuccessorAt(1, swap);
1063 1787 : }
1064 :
1065 8706634 : DECLARE_ABSTRACT_INSTRUCTION(ControlInstruction)
1066 : };
1067 :
1068 :
1069 : class HSuccessorIterator final BASE_EMBEDDED {
1070 : public:
1071 : explicit HSuccessorIterator(const HControlInstruction* instr)
1072 1951557 : : instr_(instr), current_(0) {}
1073 :
1074 62038849 : bool Done() { return current_ >= instr_->SuccessorCount(); }
1075 33092250 : HBasicBlock* Current() { return instr_->SuccessorAt(current_); }
1076 33092246 : void Advance() { current_++; }
1077 :
1078 : private:
1079 : const HControlInstruction* instr_;
1080 : int current_;
1081 : };
1082 :
1083 :
1084 : template<int S, int V>
1085 13820296 : class HTemplateControlInstruction : public HControlInstruction {
1086 : public:
1087 90964797 : int SuccessorCount() const override { return S; }
1088 64832630 : HBasicBlock* SuccessorAt(int i) const override { return successors_[i]; }
1089 1927168 : void SetSuccessorAt(int i, HBasicBlock* block) override {
1090 6147112 : successors_[i] = block;
1091 1927168 : }
1092 :
1093 5488 : int OperandCount() const override { return V; }
1094 13071632 : HValue* OperandAt(int i) const override { return inputs_[i]; }
1095 :
1096 :
1097 : protected:
1098 3079314 : void InternalSetOperandAt(int i, HValue* value) override {
1099 3079314 : inputs_[i] = value;
1100 3079314 : }
1101 :
1102 : private:
1103 : EmbeddedContainer<HBasicBlock*, S> successors_;
1104 : EmbeddedContainer<HValue*, V> inputs_;
1105 : };
1106 :
1107 :
1108 4620854 : class HBlockEntry final : public HTemplateInstruction<0> {
1109 : public:
1110 0 : Representation RequiredInputRepresentation(int index) override {
1111 0 : return Representation::None();
1112 : }
1113 :
1114 50013999 : DECLARE_CONCRETE_INSTRUCTION(BlockEntry)
1115 : };
1116 :
1117 :
1118 0 : class HDummyUse final : public HTemplateInstruction<1> {
1119 : public:
1120 : explicit HDummyUse(HValue* value)
1121 : : HTemplateInstruction<1>(HType::Smi()) {
1122 : SetOperandAt(0, value);
1123 : // Pretend to be a Smi so that the HChange instructions inserted
1124 : // before any use generate as little code as possible.
1125 : set_representation(Representation::Tagged());
1126 : }
1127 :
1128 : HValue* value() const { return OperandAt(0); }
1129 :
1130 0 : bool HasEscapingOperandAt(int index) override { return false; }
1131 0 : Representation RequiredInputRepresentation(int index) override {
1132 0 : return Representation::None();
1133 : }
1134 :
1135 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1136 :
1137 0 : DECLARE_CONCRETE_INSTRUCTION(DummyUse);
1138 : };
1139 :
1140 :
1141 : // Inserts an int3/stop break instruction for debugging purposes.
1142 0 : class HDebugBreak final : public HTemplateInstruction<0> {
1143 : public:
1144 0 : DECLARE_INSTRUCTION_FACTORY_P0(HDebugBreak);
1145 :
1146 0 : Representation RequiredInputRepresentation(int index) override {
1147 0 : return Representation::None();
1148 : }
1149 :
1150 0 : DECLARE_CONCRETE_INSTRUCTION(DebugBreak)
1151 : };
1152 :
1153 :
1154 263913 : class HPrologue final : public HTemplateInstruction<0> {
1155 : public:
1156 791739 : static HPrologue* New(Zone* zone) { return new (zone) HPrologue(); }
1157 :
1158 0 : Representation RequiredInputRepresentation(int index) override {
1159 0 : return Representation::None();
1160 : }
1161 :
1162 3116608 : DECLARE_CONCRETE_INSTRUCTION(Prologue)
1163 : };
1164 :
1165 :
1166 0 : class HGoto final : public HTemplateControlInstruction<1, 0> {
1167 : public:
1168 3033443 : explicit HGoto(HBasicBlock* target) {
1169 : SetSuccessorAt(0, target);
1170 : }
1171 :
1172 7469536 : bool KnownSuccessorBlock(HBasicBlock** block) override {
1173 7469536 : *block = FirstSuccessor();
1174 7469520 : return true;
1175 : }
1176 :
1177 0 : Representation RequiredInputRepresentation(int index) override {
1178 0 : return Representation::None();
1179 : }
1180 :
1181 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1182 :
1183 37817204 : DECLARE_CONCRETE_INSTRUCTION(Goto)
1184 : };
1185 :
1186 :
1187 0 : class HDeoptimize final : public HTemplateControlInstruction<1, 0> {
1188 : public:
1189 189474 : static HDeoptimize* New(Isolate* isolate, Zone* zone, HValue* context,
1190 : DeoptimizeReason reason,
1191 : Deoptimizer::BailoutType type,
1192 : HBasicBlock* unreachable_continuation) {
1193 189474 : return new(zone) HDeoptimize(reason, type, unreachable_continuation);
1194 : }
1195 :
1196 188914 : bool KnownSuccessorBlock(HBasicBlock** block) override {
1197 188914 : *block = NULL;
1198 188914 : return true;
1199 : }
1200 :
1201 0 : Representation RequiredInputRepresentation(int index) override {
1202 0 : return Representation::None();
1203 : }
1204 :
1205 : DeoptimizeReason reason() const { return reason_; }
1206 : Deoptimizer::BailoutType type() { return type_; }
1207 :
1208 2264042 : DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
1209 :
1210 : private:
1211 : explicit HDeoptimize(DeoptimizeReason reason, Deoptimizer::BailoutType type,
1212 : HBasicBlock* unreachable_continuation)
1213 189474 : : reason_(reason), type_(type) {
1214 : SetSuccessorAt(0, unreachable_continuation);
1215 : }
1216 :
1217 : DeoptimizeReason reason_;
1218 : Deoptimizer::BailoutType type_;
1219 : };
1220 :
1221 :
1222 0 : class HUnaryControlInstruction : public HTemplateControlInstruction<2, 1> {
1223 : public:
1224 : HUnaryControlInstruction(HValue* value,
1225 : HBasicBlock* true_target,
1226 763018 : HBasicBlock* false_target) {
1227 763018 : SetOperandAt(0, value);
1228 : SetSuccessorAt(0, true_target);
1229 : SetSuccessorAt(1, false_target);
1230 : }
1231 :
1232 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1233 :
1234 4516976 : HValue* value() const { return OperandAt(0); }
1235 : };
1236 :
1237 :
1238 0 : class HBranch final : public HUnaryControlInstruction {
1239 : public:
1240 657588 : DECLARE_INSTRUCTION_FACTORY_P1(HBranch, HValue*);
1241 622218 : DECLARE_INSTRUCTION_FACTORY_P2(HBranch, HValue*, ToBooleanHints);
1242 26998 : DECLARE_INSTRUCTION_FACTORY_P4(HBranch, HValue*, ToBooleanHints, HBasicBlock*,
1243 : HBasicBlock*);
1244 :
1245 654015 : Representation RequiredInputRepresentation(int index) override {
1246 654015 : return Representation::None();
1247 : }
1248 : Representation observed_input_representation(int index) override;
1249 :
1250 : bool KnownSuccessorBlock(HBasicBlock** block) override;
1251 :
1252 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1253 :
1254 : ToBooleanHints expected_input_types() const { return expected_input_types_; }
1255 :
1256 14179944 : DECLARE_CONCRETE_INSTRUCTION(Branch)
1257 :
1258 : private:
1259 : HBranch(HValue* value,
1260 : ToBooleanHints expected_input_types = ToBooleanHint::kNone,
1261 : HBasicBlock* true_target = NULL, HBasicBlock* false_target = NULL)
1262 : : HUnaryControlInstruction(value, true_target, false_target),
1263 653402 : expected_input_types_(expected_input_types) {}
1264 :
1265 : ToBooleanHints expected_input_types_;
1266 : };
1267 :
1268 :
1269 0 : class HCompareMap final : public HUnaryControlInstruction {
1270 : public:
1271 3654 : DECLARE_INSTRUCTION_FACTORY_P2(HCompareMap, HValue*, Handle<Map>);
1272 41120 : DECLARE_INSTRUCTION_FACTORY_P4(HCompareMap, HValue*, Handle<Map>,
1273 : HBasicBlock*, HBasicBlock*);
1274 :
1275 154261 : bool KnownSuccessorBlock(HBasicBlock** block) override {
1276 154261 : if (known_successor_index() != kNoKnownSuccessorIndex) {
1277 13068 : *block = SuccessorAt(known_successor_index());
1278 6534 : return true;
1279 : }
1280 147727 : *block = NULL;
1281 147727 : return false;
1282 : }
1283 :
1284 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1285 :
1286 : static const int kNoKnownSuccessorIndex = -1;
1287 : int known_successor_index() const {
1288 : return KnownSuccessorIndexField::decode(bit_field_) -
1289 6534 : kInternalKnownSuccessorOffset;
1290 : }
1291 : void set_known_successor_index(int index) {
1292 : DCHECK(index >= 0 - kInternalKnownSuccessorOffset);
1293 : bit_field_ = KnownSuccessorIndexField::update(
1294 6534 : bit_field_, index + kInternalKnownSuccessorOffset);
1295 : }
1296 :
1297 : Unique<Map> map() const { return map_; }
1298 : bool map_is_stable() const { return MapIsStableField::decode(bit_field_); }
1299 :
1300 31093 : Representation RequiredInputRepresentation(int index) override {
1301 31093 : return Representation::Tagged();
1302 : }
1303 :
1304 634588 : DECLARE_CONCRETE_INSTRUCTION(CompareMap)
1305 :
1306 : protected:
1307 70432 : int RedefinedOperandIndex() override { return 0; }
1308 :
1309 : private:
1310 22387 : HCompareMap(HValue* value, Handle<Map> map, HBasicBlock* true_target = NULL,
1311 : HBasicBlock* false_target = NULL)
1312 : : HUnaryControlInstruction(value, true_target, false_target),
1313 : bit_field_(KnownSuccessorIndexField::encode(
1314 : kNoKnownSuccessorIndex + kInternalKnownSuccessorOffset) |
1315 : MapIsStableField::encode(map->is_stable())),
1316 44774 : map_(Unique<Map>::CreateImmovable(map)) {
1317 : set_representation(Representation::Tagged());
1318 22387 : }
1319 :
1320 : // BitFields can only store unsigned values, so use an offset.
1321 : // Adding kInternalKnownSuccessorOffset must yield an unsigned value.
1322 : static const int kInternalKnownSuccessorOffset = 1;
1323 : STATIC_ASSERT(kNoKnownSuccessorIndex + kInternalKnownSuccessorOffset >= 0);
1324 :
1325 : class KnownSuccessorIndexField : public BitField<int, 0, 31> {};
1326 : class MapIsStableField : public BitField<bool, 31, 1> {};
1327 :
1328 : uint32_t bit_field_;
1329 : Unique<Map> map_;
1330 : };
1331 :
1332 :
1333 0 : class HContext final : public HTemplateInstruction<0> {
1334 : public:
1335 289883 : static HContext* New(Zone* zone) {
1336 289884 : return new(zone) HContext();
1337 : }
1338 :
1339 0 : Representation RequiredInputRepresentation(int index) override {
1340 0 : return Representation::None();
1341 : }
1342 :
1343 17467869 : DECLARE_CONCRETE_INSTRUCTION(Context)
1344 :
1345 : protected:
1346 0 : bool DataEquals(HValue* other) override { return true; }
1347 :
1348 : private:
1349 289884 : HContext() {
1350 : set_representation(Representation::Tagged());
1351 : SetFlag(kUseGVN);
1352 : }
1353 :
1354 358 : bool IsDeletable() const override { return true; }
1355 : };
1356 :
1357 :
1358 0 : class HReturn final : public HTemplateControlInstruction<0, 3> {
1359 : public:
1360 365938 : DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HReturn, HValue*, HValue*);
1361 : DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HReturn, HValue*);
1362 :
1363 1312352 : Representation RequiredInputRepresentation(int index) override {
1364 : // TODO(titzer): require an Int32 input for faster returns.
1365 1312352 : if (index == 2) return Representation::Smi();
1366 : return Representation::Tagged();
1367 : }
1368 :
1369 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1370 :
1371 365865 : HValue* value() const { return OperandAt(0); }
1372 37289 : HValue* context() const { return OperandAt(1); }
1373 365862 : HValue* parameter_count() const { return OperandAt(2); }
1374 :
1375 4980882 : DECLARE_CONCRETE_INSTRUCTION(Return)
1376 :
1377 : private:
1378 365938 : HReturn(HValue* context, HValue* value, HValue* parameter_count = 0) {
1379 365938 : SetOperandAt(0, value);
1380 365938 : SetOperandAt(1, context);
1381 365938 : SetOperandAt(2, parameter_count);
1382 365938 : }
1383 : };
1384 :
1385 :
1386 0 : class HAbnormalExit final : public HTemplateControlInstruction<0, 0> {
1387 : public:
1388 31598 : DECLARE_INSTRUCTION_FACTORY_P0(HAbnormalExit);
1389 :
1390 0 : Representation RequiredInputRepresentation(int index) override {
1391 0 : return Representation::None();
1392 : }
1393 :
1394 155597 : DECLARE_CONCRETE_INSTRUCTION(AbnormalExit)
1395 : private:
1396 15799 : HAbnormalExit() {}
1397 : };
1398 :
1399 :
1400 0 : class HUnaryOperation : public HTemplateInstruction<1> {
1401 : public:
1402 1407881 : explicit HUnaryOperation(HValue* value, HType type = HType::Tagged())
1403 1407881 : : HTemplateInstruction<1>(type) {
1404 1407881 : SetOperandAt(0, value);
1405 1407882 : }
1406 :
1407 : static HUnaryOperation* cast(HValue* value) {
1408 : return reinterpret_cast<HUnaryOperation*>(value);
1409 : }
1410 :
1411 : HValue* value() const { return OperandAt(0); }
1412 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1413 : };
1414 :
1415 :
1416 0 : class HUseConst final : public HUnaryOperation {
1417 : public:
1418 : DECLARE_INSTRUCTION_FACTORY_P1(HUseConst, HValue*);
1419 :
1420 0 : Representation RequiredInputRepresentation(int index) override {
1421 0 : return Representation::None();
1422 : }
1423 :
1424 0 : DECLARE_CONCRETE_INSTRUCTION(UseConst)
1425 :
1426 : private:
1427 : explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
1428 : };
1429 :
1430 :
1431 0 : class HForceRepresentation final : public HTemplateInstruction<1> {
1432 : public:
1433 : static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
1434 : HValue* value,
1435 : Representation required_representation);
1436 :
1437 : HValue* value() const { return OperandAt(0); }
1438 :
1439 83705 : Representation observed_input_representation(int index) override {
1440 : // We haven't actually *observed* this, but it's closer to the truth
1441 : // than 'None'.
1442 83705 : return representation(); // Same as the output representation.
1443 : }
1444 136215 : Representation RequiredInputRepresentation(int index) override {
1445 136215 : return representation(); // Same as the output representation.
1446 : }
1447 :
1448 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1449 :
1450 899218 : DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation)
1451 :
1452 : private:
1453 123028 : HForceRepresentation(HValue* value, Representation required_representation) {
1454 61514 : SetOperandAt(0, value);
1455 : set_representation(required_representation);
1456 61514 : }
1457 : };
1458 :
1459 0 : class HChange final : public HUnaryOperation {
1460 : public:
1461 510920 : HChange(HValue* value, Representation to, bool is_truncating_to_smi,
1462 : bool is_truncating_to_int32, bool is_truncating_to_number)
1463 510920 : : HUnaryOperation(value) {
1464 : DCHECK(!value->representation().IsNone());
1465 : DCHECK(!to.IsNone());
1466 : DCHECK(!value->representation().Equals(to));
1467 : set_representation(to);
1468 : SetFlag(kUseGVN);
1469 : SetFlag(kCanOverflow);
1470 510917 : if (is_truncating_to_smi && to.IsSmi()) {
1471 : SetFlag(kTruncatingToSmi);
1472 : SetFlag(kTruncatingToInt32);
1473 : SetFlag(kTruncatingToNumber);
1474 510917 : } else if (is_truncating_to_int32) {
1475 : SetFlag(kTruncatingToInt32);
1476 : SetFlag(kTruncatingToNumber);
1477 474758 : } else if (is_truncating_to_number) {
1478 : SetFlag(kTruncatingToNumber);
1479 : }
1480 1008903 : if (value->representation().IsSmi() || value->type().IsSmi()) {
1481 : set_type(HType::Smi());
1482 : } else {
1483 : set_type(HType::TaggedNumber());
1484 454929 : if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
1485 : }
1486 510917 : }
1487 :
1488 : HType CalculateInferredType() override;
1489 : HValue* Canonicalize() override;
1490 :
1491 : Representation from() const { return value()->representation(); }
1492 : Representation to() const { return representation(); }
1493 : bool deoptimize_on_minus_zero() const {
1494 : return CheckFlag(kBailoutOnMinusZero);
1495 : }
1496 0 : Representation RequiredInputRepresentation(int index) override {
1497 0 : return from();
1498 : }
1499 :
1500 : Range* InferRange(Zone* zone) override;
1501 :
1502 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1503 :
1504 6264845 : DECLARE_CONCRETE_INSTRUCTION(Change)
1505 :
1506 : protected:
1507 140930 : bool DataEquals(HValue* other) override { return true; }
1508 :
1509 : private:
1510 490 : bool IsDeletable() const override {
1511 733 : return !from().IsTagged() || value()->type().IsSmi();
1512 : }
1513 : };
1514 :
1515 :
1516 0 : class HClampToUint8 final : public HUnaryOperation {
1517 : public:
1518 335 : DECLARE_INSTRUCTION_FACTORY_P1(HClampToUint8, HValue*);
1519 :
1520 335 : Representation RequiredInputRepresentation(int index) override {
1521 335 : return Representation::None();
1522 : }
1523 :
1524 8234 : DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
1525 :
1526 : protected:
1527 7 : bool DataEquals(HValue* other) override { return true; }
1528 :
1529 : private:
1530 335 : explicit HClampToUint8(HValue* value)
1531 335 : : HUnaryOperation(value) {
1532 : set_representation(Representation::Integer32());
1533 : SetFlag(kTruncatingToNumber);
1534 : SetFlag(kUseGVN);
1535 335 : }
1536 :
1537 0 : bool IsDeletable() const override { return true; }
1538 : };
1539 :
1540 :
1541 : enum RemovableSimulate {
1542 : REMOVABLE_SIMULATE,
1543 : FIXED_SIMULATE
1544 : };
1545 :
1546 :
1547 : class HSimulate final : public HInstruction {
1548 : public:
1549 4964890 : HSimulate(BailoutId ast_id, int pop_count, Zone* zone,
1550 : RemovableSimulate removable)
1551 : : ast_id_(ast_id),
1552 : pop_count_(pop_count),
1553 : values_(2, zone),
1554 : assigned_indexes_(2, zone),
1555 : zone_(zone),
1556 : bit_field_(RemovableField::encode(removable) |
1557 4964890 : DoneWithReplayField::encode(false)) {}
1558 0 : ~HSimulate() {}
1559 :
1560 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1561 :
1562 : bool HasAstId() const { return !ast_id_.IsNone(); }
1563 : BailoutId ast_id() const { return ast_id_; }
1564 : void set_ast_id(BailoutId id) {
1565 : DCHECK(!HasAstId());
1566 2505644 : ast_id_ = id;
1567 : }
1568 :
1569 : int pop_count() const { return pop_count_; }
1570 : const ZoneList<HValue*>* values() const { return &values_; }
1571 : int GetAssignedIndexAt(int index) const {
1572 : DCHECK(HasAssignedIndexAt(index));
1573 : return assigned_indexes_[index];
1574 : }
1575 : bool HasAssignedIndexAt(int index) const {
1576 8041736 : return assigned_indexes_[index] != kNoIndex;
1577 : }
1578 : void AddAssignedValue(int index, HValue* value) {
1579 1340905 : AddValue(index, value);
1580 : }
1581 : void AddPushedValue(HValue* value) {
1582 2885753 : AddValue(kNoIndex, value);
1583 : }
1584 : int ToOperandIndex(int environment_index) {
1585 3440826 : for (int i = 0; i < assigned_indexes_.length(); ++i) {
1586 5160078 : if (assigned_indexes_[i] == environment_index) return i;
1587 : }
1588 : return -1;
1589 : }
1590 659118 : int OperandCount() const override { return values_.length(); }
1591 9537062 : HValue* OperandAt(int index) const override { return values_[index]; }
1592 :
1593 1864 : bool HasEscapingOperandAt(int index) override { return false; }
1594 3936486 : Representation RequiredInputRepresentation(int index) override {
1595 3936486 : return Representation::None();
1596 : }
1597 :
1598 : void MergeWith(ZoneList<HSimulate*>* list);
1599 : bool is_candidate_for_removal() {
1600 : return RemovableField::decode(bit_field_) == REMOVABLE_SIMULATE;
1601 : }
1602 :
1603 : // Replay effects of this instruction on the given environment.
1604 : void ReplayEnvironment(HEnvironment* env);
1605 :
1606 58398582 : DECLARE_CONCRETE_INSTRUCTION(Simulate)
1607 :
1608 : #ifdef DEBUG
1609 : void Verify() override;
1610 : void set_closure(Handle<JSFunction> closure) { closure_ = closure; }
1611 : Handle<JSFunction> closure() const { return closure_; }
1612 : #endif
1613 :
1614 : protected:
1615 4818478 : void InternalSetOperandAt(int index, HValue* value) override {
1616 9636956 : values_[index] = value;
1617 4818478 : }
1618 :
1619 : private:
1620 : static const int kNoIndex = -1;
1621 4226657 : void AddValue(int index, HValue* value) {
1622 4226657 : assigned_indexes_.Add(index, zone_);
1623 : // Resize the list of pushed values.
1624 4226657 : values_.Add(NULL, zone_);
1625 : // Set the operand through the base method in HValue to make sure that the
1626 : // use lists are correctly updated.
1627 4226656 : SetOperandAt(values_.length() - 1, value);
1628 4226657 : }
1629 : bool HasValueForIndex(int index) {
1630 155442 : for (int i = 0; i < assigned_indexes_.length(); ++i) {
1631 239734 : if (assigned_indexes_[i] == index) return true;
1632 : }
1633 : return false;
1634 : }
1635 : bool is_done_with_replay() const {
1636 : return DoneWithReplayField::decode(bit_field_);
1637 : }
1638 : void set_done_with_replay() {
1639 9479974 : bit_field_ = DoneWithReplayField::update(bit_field_, true);
1640 : }
1641 :
1642 : class RemovableField : public BitField<RemovableSimulate, 0, 1> {};
1643 : class DoneWithReplayField : public BitField<bool, 1, 1> {};
1644 :
1645 : BailoutId ast_id_;
1646 : int pop_count_;
1647 : ZoneList<HValue*> values_;
1648 : ZoneList<int> assigned_indexes_;
1649 : Zone* zone_;
1650 : uint32_t bit_field_;
1651 :
1652 : #ifdef DEBUG
1653 : Handle<JSFunction> closure_;
1654 : #endif
1655 : };
1656 :
1657 :
1658 0 : class HEnvironmentMarker final : public HTemplateInstruction<1> {
1659 : public:
1660 : enum Kind { BIND, LOOKUP };
1661 :
1662 2562564 : DECLARE_INSTRUCTION_FACTORY_P2(HEnvironmentMarker, Kind, int);
1663 :
1664 : Kind kind() const { return kind_; }
1665 : int index() const { return index_; }
1666 : HSimulate* next_simulate() { return next_simulate_; }
1667 : void set_next_simulate(HSimulate* simulate) {
1668 1493781 : next_simulate_ = simulate;
1669 : }
1670 :
1671 0 : Representation RequiredInputRepresentation(int index) override {
1672 0 : return Representation::None();
1673 : }
1674 :
1675 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1676 :
1677 : #ifdef DEBUG
1678 : void set_closure(Handle<JSFunction> closure) {
1679 : DCHECK(closure_.is_null());
1680 : DCHECK(!closure.is_null());
1681 : closure_ = closure;
1682 : }
1683 : Handle<JSFunction> closure() const { return closure_; }
1684 : #endif
1685 :
1686 1571170 : DECLARE_CONCRETE_INSTRUCTION(EnvironmentMarker);
1687 :
1688 : private:
1689 : HEnvironmentMarker(Kind kind, int index)
1690 1281282 : : kind_(kind), index_(index), next_simulate_(NULL) { }
1691 :
1692 : Kind kind_;
1693 : int index_;
1694 : HSimulate* next_simulate_;
1695 :
1696 : #ifdef DEBUG
1697 : Handle<JSFunction> closure_;
1698 : #endif
1699 : };
1700 :
1701 :
1702 0 : class HStackCheck final : public HTemplateInstruction<1> {
1703 : public:
1704 : enum Type {
1705 : kFunctionEntry,
1706 : kBackwardsBranch
1707 : };
1708 :
1709 309501 : DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HStackCheck, Type);
1710 :
1711 : HValue* context() { return OperandAt(0); }
1712 :
1713 309082 : Representation RequiredInputRepresentation(int index) override {
1714 309082 : return Representation::Tagged();
1715 : }
1716 :
1717 : void Eliminate() {
1718 : // The stack check eliminator might try to eliminate the same stack
1719 : // check instruction multiple times.
1720 4170 : if (IsLinked()) {
1721 4010 : DeleteAndReplaceWith(NULL);
1722 : }
1723 : }
1724 :
1725 : bool is_function_entry() { return type_ == kFunctionEntry; }
1726 : bool is_backwards_branch() { return type_ == kBackwardsBranch; }
1727 :
1728 3802275 : DECLARE_CONCRETE_INSTRUCTION(StackCheck)
1729 :
1730 : private:
1731 619002 : HStackCheck(HValue* context, Type type) : type_(type) {
1732 309501 : SetOperandAt(0, context);
1733 : SetChangesFlag(kNewSpacePromotion);
1734 309501 : }
1735 :
1736 : Type type_;
1737 : };
1738 :
1739 :
1740 : enum InliningKind {
1741 : NORMAL_RETURN, // Drop the function from the environment on return.
1742 : CONSTRUCT_CALL_RETURN, // Either use allocated receiver or return value.
1743 : GETTER_CALL_RETURN, // Returning from a getter, need to restore context.
1744 : SETTER_CALL_RETURN // Use the RHS of the assignment as the return value.
1745 : };
1746 :
1747 :
1748 : class HArgumentsObject;
1749 : class HConstant;
1750 :
1751 :
1752 0 : class HEnterInlined final : public HTemplateInstruction<0> {
1753 : public:
1754 107398 : static HEnterInlined* New(Isolate* isolate, Zone* zone, HValue* context,
1755 : BailoutId return_id, Handle<JSFunction> closure,
1756 : HConstant* closure_context, int arguments_count,
1757 : FunctionLiteral* function,
1758 : InliningKind inlining_kind, Variable* arguments_var,
1759 : HArgumentsObject* arguments_object,
1760 : TailCallMode syntactic_tail_call_mode) {
1761 : return new (zone)
1762 : HEnterInlined(return_id, closure, closure_context, arguments_count,
1763 : function, inlining_kind, arguments_var, arguments_object,
1764 214796 : syntactic_tail_call_mode, zone);
1765 : }
1766 :
1767 : void RegisterReturnTarget(HBasicBlock* return_target, Zone* zone);
1768 : ZoneList<HBasicBlock*>* return_targets() { return &return_targets_; }
1769 :
1770 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
1771 :
1772 : Handle<SharedFunctionInfo> shared() const { return shared_; }
1773 : Handle<JSFunction> closure() const { return closure_; }
1774 : HConstant* closure_context() const { return closure_context_; }
1775 : int arguments_count() const { return arguments_count_; }
1776 : bool arguments_pushed() const { return arguments_pushed_; }
1777 232 : void set_arguments_pushed() { arguments_pushed_ = true; }
1778 : FunctionLiteral* function() const { return function_; }
1779 : InliningKind inlining_kind() const { return inlining_kind_; }
1780 : TailCallMode syntactic_tail_call_mode() const {
1781 : return syntactic_tail_call_mode_;
1782 : }
1783 : BailoutId ReturnId() const { return return_id_; }
1784 : int inlining_id() const { return inlining_id_; }
1785 3 : void set_inlining_id(int inlining_id) { inlining_id_ = inlining_id; }
1786 :
1787 0 : Representation RequiredInputRepresentation(int index) override {
1788 0 : return Representation::None();
1789 : }
1790 :
1791 : Variable* arguments_var() { return arguments_var_; }
1792 : HArgumentsObject* arguments_object() { return arguments_object_; }
1793 :
1794 1300678 : DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
1795 :
1796 : private:
1797 107398 : HEnterInlined(BailoutId return_id, Handle<JSFunction> closure,
1798 : HConstant* closure_context, int arguments_count,
1799 : FunctionLiteral* function, InliningKind inlining_kind,
1800 : Variable* arguments_var, HArgumentsObject* arguments_object,
1801 : TailCallMode syntactic_tail_call_mode, Zone* zone)
1802 : : return_id_(return_id),
1803 : shared_(handle(closure->shared())),
1804 : closure_(closure),
1805 : closure_context_(closure_context),
1806 : arguments_count_(arguments_count),
1807 : arguments_pushed_(false),
1808 : function_(function),
1809 : inlining_kind_(inlining_kind),
1810 : syntactic_tail_call_mode_(syntactic_tail_call_mode),
1811 : inlining_id_(-1),
1812 : arguments_var_(arguments_var),
1813 : arguments_object_(arguments_object),
1814 214796 : return_targets_(2, zone) {}
1815 :
1816 : BailoutId return_id_;
1817 : Handle<SharedFunctionInfo> shared_;
1818 : Handle<JSFunction> closure_;
1819 : HConstant* closure_context_;
1820 : int arguments_count_;
1821 : bool arguments_pushed_;
1822 : FunctionLiteral* function_;
1823 : InliningKind inlining_kind_;
1824 : TailCallMode syntactic_tail_call_mode_;
1825 : int inlining_id_;
1826 : Variable* arguments_var_;
1827 : HArgumentsObject* arguments_object_;
1828 : ZoneList<HBasicBlock*> return_targets_;
1829 : };
1830 :
1831 :
1832 0 : class HLeaveInlined final : public HTemplateInstruction<0> {
1833 : public:
1834 : HLeaveInlined(HEnterInlined* entry,
1835 : int drop_count)
1836 : : entry_(entry),
1837 562667 : drop_count_(drop_count) { }
1838 :
1839 0 : Representation RequiredInputRepresentation(int index) override {
1840 0 : return Representation::None();
1841 : }
1842 :
1843 558631 : int argument_delta() const override {
1844 558631 : return entry_->arguments_pushed() ? -drop_count_ : 0;
1845 : }
1846 :
1847 5951523 : DECLARE_CONCRETE_INSTRUCTION(LeaveInlined)
1848 :
1849 : private:
1850 : HEnterInlined* entry_;
1851 : int drop_count_;
1852 : };
1853 :
1854 :
1855 0 : class HPushArguments final : public HInstruction {
1856 : public:
1857 597064 : static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context) {
1858 597064 : return new(zone) HPushArguments(zone);
1859 : }
1860 35747 : static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
1861 : HValue* arg1) {
1862 35747 : HPushArguments* instr = new(zone) HPushArguments(zone);
1863 35747 : instr->AddInput(arg1);
1864 35747 : return instr;
1865 : }
1866 8061 : static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
1867 : HValue* arg1, HValue* arg2) {
1868 8061 : HPushArguments* instr = new(zone) HPushArguments(zone);
1869 8061 : instr->AddInput(arg1);
1870 8061 : instr->AddInput(arg2);
1871 8061 : return instr;
1872 : }
1873 1165 : static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
1874 : HValue* arg1, HValue* arg2, HValue* arg3) {
1875 1165 : HPushArguments* instr = new(zone) HPushArguments(zone);
1876 1165 : instr->AddInput(arg1);
1877 1165 : instr->AddInput(arg2);
1878 1165 : instr->AddInput(arg3);
1879 1165 : return instr;
1880 : }
1881 33528 : static HPushArguments* New(Isolate* isolate, Zone* zone, HValue* context,
1882 : HValue* arg1, HValue* arg2, HValue* arg3,
1883 : HValue* arg4) {
1884 33528 : HPushArguments* instr = new(zone) HPushArguments(zone);
1885 33528 : instr->AddInput(arg1);
1886 33528 : instr->AddInput(arg2);
1887 33528 : instr->AddInput(arg3);
1888 33528 : instr->AddInput(arg4);
1889 33528 : return instr;
1890 : }
1891 :
1892 1903758 : Representation RequiredInputRepresentation(int index) override {
1893 1903758 : return Representation::Tagged();
1894 : }
1895 :
1896 670750 : int argument_delta() const override { return inputs_.length(); }
1897 : HValue* argument(int i) { return OperandAt(i); }
1898 :
1899 2497670 : int OperandCount() const final { return inputs_.length(); }
1900 7241664 : HValue* OperandAt(int i) const final { return inputs_[i]; }
1901 :
1902 : void AddInput(HValue* value);
1903 :
1904 10052242 : DECLARE_CONCRETE_INSTRUCTION(PushArguments)
1905 :
1906 : protected:
1907 4338868 : void InternalSetOperandAt(int i, HValue* value) final { inputs_[i] = value; }
1908 :
1909 : private:
1910 675565 : explicit HPushArguments(Zone* zone)
1911 675565 : : HInstruction(HType::Tagged()), inputs_(4, zone) {
1912 : set_representation(Representation::Tagged());
1913 675565 : }
1914 :
1915 : ZoneList<HValue*> inputs_;
1916 : };
1917 :
1918 :
1919 0 : class HThisFunction final : public HTemplateInstruction<0> {
1920 : public:
1921 89072 : DECLARE_INSTRUCTION_FACTORY_P0(HThisFunction);
1922 :
1923 0 : Representation RequiredInputRepresentation(int index) override {
1924 0 : return Representation::None();
1925 : }
1926 :
1927 819435 : DECLARE_CONCRETE_INSTRUCTION(ThisFunction)
1928 :
1929 : protected:
1930 16579 : bool DataEquals(HValue* other) override { return true; }
1931 :
1932 : private:
1933 44536 : HThisFunction() {
1934 : set_representation(Representation::Tagged());
1935 : SetFlag(kUseGVN);
1936 : }
1937 :
1938 32 : bool IsDeletable() const override { return true; }
1939 : };
1940 :
1941 :
1942 0 : class HDeclareGlobals final : public HUnaryOperation {
1943 : public:
1944 24860 : DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HDeclareGlobals,
1945 : Handle<FixedArray>, int,
1946 : Handle<FeedbackVector>);
1947 :
1948 : HValue* context() { return OperandAt(0); }
1949 : Handle<FixedArray> declarations() const { return declarations_; }
1950 : int flags() const { return flags_; }
1951 : Handle<FeedbackVector> feedback_vector() const { return feedback_vector_; }
1952 :
1953 197584 : DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals)
1954 :
1955 12333 : Representation RequiredInputRepresentation(int index) override {
1956 12333 : return Representation::Tagged();
1957 : }
1958 :
1959 : private:
1960 : HDeclareGlobals(HValue* context, Handle<FixedArray> declarations, int flags,
1961 : Handle<FeedbackVector> feedback_vector)
1962 : : HUnaryOperation(context),
1963 : declarations_(declarations),
1964 : feedback_vector_(feedback_vector),
1965 12430 : flags_(flags) {
1966 : set_representation(Representation::Tagged());
1967 : SetAllSideEffects();
1968 : }
1969 :
1970 : Handle<FixedArray> declarations_;
1971 : Handle<FeedbackVector> feedback_vector_;
1972 : int flags_;
1973 : };
1974 :
1975 :
1976 : template <int V>
1977 0 : class HCall : public HTemplateInstruction<V> {
1978 : public:
1979 : // The argument count includes the receiver.
1980 506416 : explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
1981 : this->set_representation(Representation::Tagged());
1982 : this->SetAllSideEffects();
1983 253208 : }
1984 :
1985 482145 : virtual int argument_count() const {
1986 482145 : return argument_count_;
1987 : }
1988 :
1989 251194 : int argument_delta() const override { return -argument_count(); }
1990 :
1991 : private:
1992 : int argument_count_;
1993 : };
1994 :
1995 :
1996 0 : class HUnaryCall : public HCall<1> {
1997 : public:
1998 : HUnaryCall(HValue* value, int argument_count)
1999 : : HCall<1>(argument_count) {
2000 : SetOperandAt(0, value);
2001 : }
2002 :
2003 0 : Representation RequiredInputRepresentation(int index) final {
2004 0 : return Representation::Tagged();
2005 : }
2006 :
2007 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
2008 :
2009 : HValue* value() const { return OperandAt(0); }
2010 : };
2011 :
2012 :
2013 0 : class HBinaryCall : public HCall<2> {
2014 : public:
2015 146006 : HBinaryCall(HValue* first, HValue* second, int argument_count)
2016 146006 : : HCall<2>(argument_count) {
2017 146006 : SetOperandAt(0, first);
2018 146006 : SetOperandAt(1, second);
2019 146006 : }
2020 :
2021 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
2022 :
2023 291961 : Representation RequiredInputRepresentation(int index) final {
2024 291961 : return Representation::Tagged();
2025 : }
2026 :
2027 : HValue* first() const { return OperandAt(0); }
2028 : HValue* second() const { return OperandAt(1); }
2029 : };
2030 :
2031 :
2032 0 : class HCallWithDescriptor final : public HInstruction {
2033 : public:
2034 530164 : static HCallWithDescriptor* New(
2035 : Isolate* isolate, Zone* zone, HValue* context, HValue* target,
2036 : int argument_count, CallInterfaceDescriptor descriptor,
2037 : const Vector<HValue*>& operands,
2038 : TailCallMode syntactic_tail_call_mode = TailCallMode::kDisallow,
2039 : TailCallMode tail_call_mode = TailCallMode::kDisallow) {
2040 : HCallWithDescriptor* res = new (zone) HCallWithDescriptor(
2041 : Code::STUB, context, target, argument_count, descriptor, operands,
2042 530164 : syntactic_tail_call_mode, tail_call_mode, zone);
2043 530164 : return res;
2044 : }
2045 :
2046 484017 : static HCallWithDescriptor* New(
2047 : Isolate* isolate, Zone* zone, HValue* context, Code::Kind kind,
2048 : HValue* target, int argument_count, CallInterfaceDescriptor descriptor,
2049 : const Vector<HValue*>& operands,
2050 : TailCallMode syntactic_tail_call_mode = TailCallMode::kDisallow,
2051 : TailCallMode tail_call_mode = TailCallMode::kDisallow) {
2052 : HCallWithDescriptor* res = new (zone) HCallWithDescriptor(
2053 : kind, context, target, argument_count, descriptor, operands,
2054 484017 : syntactic_tail_call_mode, tail_call_mode, zone);
2055 484017 : return res;
2056 : }
2057 :
2058 1905054 : int OperandCount() const final { return values_.length(); }
2059 24518520 : HValue* OperandAt(int index) const final { return values_[index]; }
2060 :
2061 6367375 : Representation RequiredInputRepresentation(int index) final {
2062 6367375 : if (index == 0 || index == 1) {
2063 : // Target + context
2064 : return Representation::Tagged();
2065 : } else {
2066 4350032 : int par_index = index - 2;
2067 : DCHECK(par_index < GetParameterCount());
2068 : return RepresentationFromMachineType(
2069 4350032 : descriptor_.GetParameterType(par_index));
2070 : }
2071 : }
2072 :
2073 45310784 : DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor)
2074 :
2075 : // Defines whether this instruction corresponds to a JS call at tail position.
2076 : TailCallMode syntactic_tail_call_mode() const {
2077 : return SyntacticTailCallModeField::decode(bit_field_);
2078 : }
2079 :
2080 : // Defines whether this call should be generated as a tail call.
2081 : TailCallMode tail_call_mode() const {
2082 : return TailCallModeField::decode(bit_field_);
2083 : }
2084 848446 : bool IsTailCall() const { return tail_call_mode() == TailCallMode::kAllow; }
2085 :
2086 : Code::Kind kind() const { return KindField::decode(bit_field_); }
2087 :
2088 0 : virtual int argument_count() const {
2089 0 : return argument_count_;
2090 : }
2091 :
2092 1007170 : int argument_delta() const override { return -argument_count_; }
2093 :
2094 : CallInterfaceDescriptor descriptor() const { return descriptor_; }
2095 :
2096 : HValue* target() { return OperandAt(0); }
2097 : HValue* context() { return OperandAt(1); }
2098 : HValue* parameter(int index) {
2099 : DCHECK_LT(index, GetParameterCount());
2100 : return OperandAt(index + 2);
2101 : }
2102 :
2103 : HValue* Canonicalize() override;
2104 :
2105 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
2106 :
2107 : private:
2108 : // The argument count includes the receiver.
2109 1014181 : HCallWithDescriptor(Code::Kind kind, HValue* context, HValue* target,
2110 : int argument_count, CallInterfaceDescriptor descriptor,
2111 8385457 : const Vector<HValue*>& operands,
2112 : TailCallMode syntactic_tail_call_mode,
2113 : TailCallMode tail_call_mode, Zone* zone)
2114 : : descriptor_(descriptor),
2115 : values_(GetParameterCount() + 2, zone), // +2 for context and target.
2116 : argument_count_(argument_count),
2117 : bit_field_(
2118 1014181 : TailCallModeField::encode(tail_call_mode) |
2119 1014181 : SyntacticTailCallModeField::encode(syntactic_tail_call_mode) |
2120 3042543 : KindField::encode(kind)) {
2121 : DCHECK_EQ(operands.length(), GetParameterCount());
2122 : // We can only tail call without any stack arguments.
2123 : DCHECK(tail_call_mode != TailCallMode::kAllow || argument_count == 0);
2124 1014181 : AddOperand(target, zone);
2125 1014181 : AddOperand(context, zone);
2126 9399638 : for (int i = 0; i < operands.length(); i++) {
2127 3685638 : AddOperand(operands[i], zone);
2128 : }
2129 : this->set_representation(Representation::Tagged());
2130 : this->SetAllSideEffects();
2131 1014181 : }
2132 :
2133 5713998 : void AddOperand(HValue* v, Zone* zone) {
2134 : values_.Add(NULL, zone);
2135 5713998 : SetOperandAt(values_.length() - 1, v);
2136 5713999 : }
2137 :
2138 : int GetParameterCount() const { return descriptor_.GetParameterCount(); }
2139 :
2140 8921803 : void InternalSetOperandAt(int index, HValue* value) final {
2141 17843606 : values_[index] = value;
2142 8921803 : }
2143 :
2144 : CallInterfaceDescriptor descriptor_;
2145 : ZoneList<HValue*> values_;
2146 : int argument_count_;
2147 : class TailCallModeField : public BitField<TailCallMode, 0, 1> {};
2148 : class SyntacticTailCallModeField
2149 : : public BitField<TailCallMode, TailCallModeField::kNext, 1> {};
2150 : class KindField
2151 : : public BitField<Code::Kind, SyntacticTailCallModeField::kNext, 5> {};
2152 : uint32_t bit_field_;
2153 : };
2154 :
2155 :
2156 0 : class HInvokeFunction final : public HBinaryCall {
2157 : public:
2158 291200 : DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(HInvokeFunction, HValue*,
2159 : Handle<JSFunction>, int,
2160 : TailCallMode, TailCallMode);
2161 :
2162 : HValue* context() { return first(); }
2163 : HValue* function() { return second(); }
2164 : Handle<JSFunction> known_function() { return known_function_; }
2165 : int formal_parameter_count() const { return formal_parameter_count_; }
2166 :
2167 16448 : bool HasStackCheck() final { return HasStackCheckField::decode(bit_field_); }
2168 :
2169 : // Defines whether this instruction corresponds to a JS call at tail position.
2170 : TailCallMode syntactic_tail_call_mode() const {
2171 : return SyntacticTailCallModeField::decode(bit_field_);
2172 : }
2173 :
2174 : // Defines whether this call should be generated as a tail call.
2175 : TailCallMode tail_call_mode() const {
2176 : return TailCallModeField::decode(bit_field_);
2177 : }
2178 :
2179 9231437 : DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
2180 :
2181 : std::ostream& PrintTo(std::ostream& os) const override; // NOLINT
2182 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
2183 :
2184 : private:
2185 : void set_has_stack_check(bool has_stack_check) {
2186 145600 : bit_field_ = HasStackCheckField::update(bit_field_, has_stack_check);
2187 : }
2188 :
2189 145600 : HInvokeFunction(HValue* context, HValue* function,
2190 : Handle<JSFunction> known_function, int argument_count,
2191 : TailCallMode syntactic_tail_call_mode,
2192 : TailCallMode tail_call_mode)
2193 : : HBinaryCall(context, function, argument_count),
2194 : known_function_(known_function),
2195 : bit_field_(
2196 145600 : TailCallModeField::encode(tail_call_mode) |
2197 291200 : SyntacticTailCallModeField::encode(syntactic_tail_call_mode)) {
2198 : DCHECK(tail_call_mode != TailCallMode::kAllow ||
2199 : syntactic_tail_call_mode == TailCallMode::kAllow);
2200 : formal_parameter_count_ =
2201 : known_function.is_null()
2202 : ? 0
2203 291200 : : known_function->shared()->internal_formal_parameter_count();
2204 : set_has_stack_check(
2205 286207 : !known_function.is_null() &&
2206 128794 : (known_function->code()->kind() == Code::FUNCTION ||
2207 : known_function->code()->kind() == Code::OPTIMIZED_FUNCTION));
2208 145600 : }
2209 :
2210 : Handle<JSFunction> known_function_;
2211 : int formal_parameter_count_;
2212 :
2213 : class HasStackCheckField : public BitField<bool, 0, 1> {};
2214 : class TailCallModeField
2215 : : public BitField<TailCallMode, HasStackCheckField::kNext, 1> {};
2216 : class SyntacticTailCallModeField
2217 : : public BitField<TailCallMode, TailCallModeField::kNext, 1> {};
2218 : uint32_t bit_field_;
2219 : };
2220 :
2221 :
2222 0 : class HCallNewArray final : public HBinaryCall {
2223 : public:
2224 812 : DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HCallNewArray, HValue*, int,
2225 : ElementsKind,
2226 : Handle<AllocationSite>);
2227 :
2228 : HValue* context() { return first(); }
2229 : HValue* constructor() { return second(); }
2230 :
2231 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
2232 :
2233 : ElementsKind elements_kind() const { return elements_kind_; }
2234 : Handle<AllocationSite> site() const { return site_; }
2235 :
2236 60113 : DECLARE_CONCRETE_INSTRUCTION(CallNewArray)
2237 :
2238 : private:
2239 : HCallNewArray(HValue* context, HValue* constructor, int argument_count,
2240 : ElementsKind elements_kind, Handle<AllocationSite> site)
2241 : : HBinaryCall(context, constructor, argument_count),
2242 : elements_kind_(elements_kind),
2243 406 : site_(site) {}
2244 :
2245 : ElementsKind elements_kind_;
2246 : Handle<AllocationSite> site_;
2247 : };
2248 :
2249 :
2250 0 : class HCallRuntime final : public HCall<1> {
2251 : public:
2252 107202 : DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallRuntime,
2253 : const Runtime::Function*, int);
2254 :
2255 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
2256 :
2257 : HValue* context() { return OperandAt(0); }
2258 : const Runtime::Function* function() const { return c_function_; }
2259 : SaveFPRegsMode save_doubles() const { return save_doubles_; }
2260 : void set_save_doubles(SaveFPRegsMode save_doubles) {
2261 12546 : save_doubles_ = save_doubles;
2262 : }
2263 :
2264 108161 : Representation RequiredInputRepresentation(int index) override {
2265 108161 : return Representation::Tagged();
2266 : }
2267 :
2268 5218089 : DECLARE_CONCRETE_INSTRUCTION(CallRuntime)
2269 :
2270 : private:
2271 107202 : HCallRuntime(HValue* context, const Runtime::Function* c_function,
2272 : int argument_count)
2273 : : HCall<1>(argument_count),
2274 : c_function_(c_function),
2275 107202 : save_doubles_(kDontSaveFPRegs) {
2276 107202 : SetOperandAt(0, context);
2277 107202 : }
2278 :
2279 : const Runtime::Function* c_function_;
2280 : SaveFPRegsMode save_doubles_;
2281 : };
2282 :
2283 :
2284 0 : class HUnaryMathOperation final : public HTemplateInstruction<2> {
2285 : public:
2286 : static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
2287 : HValue* value, BuiltinFunctionId op);
2288 :
2289 : HValue* context() const { return OperandAt(0); }
2290 : HValue* value() const { return OperandAt(1); }
2291 :
2292 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
2293 :
2294 102909 : Representation RequiredInputRepresentation(int index) override {
2295 102909 : if (index == 0) {
2296 : return Representation::Tagged();
2297 : } else {
2298 53257 : switch (op_) {
2299 : case kMathCos:
2300 : case kMathFloor:
2301 : case kMathRound:
2302 : case kMathFround:
2303 : case kMathSin:
2304 : case kMathSqrt:
2305 : case kMathPowHalf:
2306 : case kMathLog:
2307 : case kMathExp:
2308 : return Representation::Double();
2309 : case kMathAbs:
2310 : return representation();
2311 : case kMathClz32:
2312 : return Representation::Integer32();
2313 : default:
2314 0 : UNREACHABLE();
2315 : return Representation::None();
2316 : }
2317 : }
2318 : }
2319 :
2320 : Range* InferRange(Zone* zone) override;
2321 :
2322 : HValue* Canonicalize() override;
2323 : Representation RepresentationFromUses() override;
2324 : Representation RepresentationFromInputs() override;
2325 :
2326 : BuiltinFunctionId op() const { return op_; }
2327 : const char* OpName() const;
2328 :
2329 730367 : DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)
2330 :
2331 : protected:
2332 164 : bool DataEquals(HValue* other) override {
2333 164 : HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
2334 328 : return op_ == b->op();
2335 : }
2336 :
2337 : private:
2338 : // Indicates if we support a double (and int32) output for Math.floor and
2339 : // Math.round.
2340 : bool SupportsFlexibleFloorAndRound() const {
2341 : #if V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_PPC
2342 : return true;
2343 : #elif V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
2344 : return CpuFeatures::IsSupported(SSE4_1);
2345 : #else
2346 : return false;
2347 : #endif
2348 : }
2349 29288 : HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
2350 29288 : : HTemplateInstruction<2>(HType::TaggedNumber()), op_(op) {
2351 29288 : SetOperandAt(0, context);
2352 29288 : SetOperandAt(1, value);
2353 29288 : switch (op) {
2354 : case kMathFloor:
2355 : case kMathRound:
2356 27563 : if (SupportsFlexibleFloorAndRound()) {
2357 : SetFlag(kFlexibleRepresentation);
2358 : } else {
2359 : set_representation(Representation::Integer32());
2360 : }
2361 : break;
2362 : case kMathClz32:
2363 : set_representation(Representation::Integer32());
2364 : break;
2365 : case kMathAbs:
2366 : // Not setting representation here: it is None intentionally.
2367 : SetFlag(kFlexibleRepresentation);
2368 : // TODO(svenpanne) This flag is actually only needed if representation()
2369 : // is tagged, and not when it is an unboxed double or unboxed integer.
2370 : SetChangesFlag(kNewSpacePromotion);
2371 : break;
2372 : case kMathCos:
2373 : case kMathFround:
2374 : case kMathLog:
2375 : case kMathExp:
2376 : case kMathSin:
2377 : case kMathSqrt:
2378 : case kMathPowHalf:
2379 : set_representation(Representation::Double());
2380 : break;
2381 : default:
2382 0 : UNREACHABLE();
2383 : }
2384 : SetFlag(kUseGVN);
2385 : SetFlag(kTruncatingToNumber);
2386 29288 : }
2387 :
2388 72 : bool IsDeletable() const override {
2389 : // TODO(crankshaft): This should be true, however the semantics of this
2390 : // instruction also include the ToNumber conversion that is mentioned in the
2391 : // spec, which is of course observable.
2392 72 : return false;
2393 : }
2394 :
2395 : HValue* SimplifiedDividendForMathFloorOfDiv(HDiv* hdiv);
2396 : HValue* SimplifiedDivisorForMathFloorOfDiv(HDiv* hdiv);
2397 :
2398 : BuiltinFunctionId op_;
2399 : };
2400 :
2401 :
2402 0 : class HLoadRoot final : public HTemplateInstruction<0> {
2403 : public:
2404 10878 : DECLARE_INSTRUCTION_FACTORY_P1(HLoadRoot, Heap::RootListIndex);
2405 : DECLARE_INSTRUCTION_FACTORY_P2(HLoadRoot, Heap::RootListIndex, HType);
2406 :
2407 0 : Representation RequiredInputRepresentation(int index) override {
2408 0 : return Representation::None();
2409 : }
2410 :
2411 : Heap::RootListIndex index() const { return index_; }
2412 :
2413 104746 : DECLARE_CONCRETE_INSTRUCTION(LoadRoot)
2414 :
2415 : protected:
2416 19 : bool DataEquals(HValue* other) override {
2417 : HLoadRoot* b = HLoadRoot::cast(other);
2418 19 : return index_ == b->index_;
2419 : }
2420 :
2421 : private:
2422 : explicit HLoadRoot(Heap::RootListIndex index, HType type = HType::Tagged())
2423 5439 : : HTemplateInstruction<0>(type), index_(index) {
2424 : SetFlag(kUseGVN);
2425 : // TODO(bmeurer): We'll need kDependsOnRoots once we add the
2426 : // corresponding HStoreRoot instruction.
2427 : SetDependsOnFlag(kCalls);
2428 : set_representation(Representation::Tagged());
2429 : }
2430 :
2431 0 : bool IsDeletable() const override { return true; }
2432 :
2433 : const Heap::RootListIndex index_;
2434 : };
2435 :
2436 :
2437 0 : class HCheckMaps final : public HTemplateInstruction<2> {
2438 : public:
2439 144038 : static HCheckMaps* New(Isolate* isolate, Zone* zone, HValue* context,
2440 : HValue* value, Handle<Map> map,
2441 : HValue* typecheck = NULL) {
2442 : return new(zone) HCheckMaps(value, new(zone) UniqueSet<Map>(
2443 144038 : Unique<Map>::CreateImmovable(map), zone), typecheck);
2444 : }
2445 180420 : static HCheckMaps* New(Isolate* isolate, Zone* zone, HValue* context,
2446 : HValue* value, SmallMapList* map_list,
2447 : HValue* typecheck = NULL) {
2448 : UniqueSet<Map>* maps = new(zone) UniqueSet<Map>(map_list->length(), zone);
2449 735246 : for (int i = 0; i < map_list->length(); ++i) {
2450 187203 : maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone);
2451 : }
2452 180420 : return new(zone) HCheckMaps(value, maps, typecheck);
2453 : }
2454 :
2455 : bool IsStabilityCheck() const {
2456 : return IsStabilityCheckField::decode(bit_field_);
2457 : }
2458 : void MarkAsStabilityCheck() {
2459 : bit_field_ = MapsAreStableField::encode(true) |
2460 : HasMigrationTargetField::encode(false) |
2461 199880 : IsStabilityCheckField::encode(true);
2462 : ClearChangesFlag(kNewSpacePromotion);
2463 : ClearDependsOnFlag(kElementsKind);
2464 : ClearDependsOnFlag(kMaps);
2465 : }
2466 :
2467 6490 : bool HasEscapingOperandAt(int index) override { return false; }
2468 648055 : Representation RequiredInputRepresentation(int index) override {
2469 648055 : return Representation::Tagged();
2470 : }
2471 :
2472 319301 : HType CalculateInferredType() override {
2473 319301 : if (value()->type().IsHeapObject()) return value()->type();
2474 : return HType::HeapObject();
2475 : }
2476 :
2477 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
2478 :
2479 : HValue* value() const { return OperandAt(0); }
2480 : HValue* typecheck() const { return OperandAt(1); }
2481 :
2482 : const UniqueSet<Map>* maps() const { return maps_; }
2483 14898 : void set_maps(const UniqueSet<Map>* maps) { maps_ = maps; }
2484 :
2485 : bool maps_are_stable() const {
2486 : return MapsAreStableField::decode(bit_field_);
2487 : }
2488 :
2489 : bool HasMigrationTarget() const {
2490 : return HasMigrationTargetField::decode(bit_field_);
2491 : }
2492 :
2493 : HValue* Canonicalize() override;
2494 :
2495 0 : static HCheckMaps* CreateAndInsertAfter(Zone* zone,
2496 : HValue* value,
2497 : Unique<Map> map,
2498 : bool map_is_stable,
2499 : HInstruction* instr) {
2500 : return instr->Append(new(zone) HCheckMaps(
2501 0 : value, new(zone) UniqueSet<Map>(map, zone), map_is_stable));
2502 : }
2503 :
2504 722 : static HCheckMaps* CreateAndInsertBefore(Zone* zone,
2505 : HValue* value,
2506 : const UniqueSet<Map>* maps,
2507 : bool maps_are_stable,
2508 : HInstruction* instr) {
2509 1444 : return instr->Prepend(new(zone) HCheckMaps(value, maps, maps_are_stable));
2510 : }
2511 :
2512 5081189 : DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
2513 :
2514 : protected:
2515 225510 : bool DataEquals(HValue* other) override {
2516 338265 : return this->maps()->Equals(HCheckMaps::cast(other)->maps());
2517 : }
2518 :
2519 592952 : int RedefinedOperandIndex() override { return 0; }
2520 :
2521 : private:
2522 722 : HCheckMaps(HValue* value, const UniqueSet<Map>* maps, bool maps_are_stable)
2523 : : HTemplateInstruction<2>(HType::HeapObject()),
2524 : maps_(maps),
2525 : bit_field_(HasMigrationTargetField::encode(false) |
2526 : IsStabilityCheckField::encode(false) |
2527 1444 : MapsAreStableField::encode(maps_are_stable)) {
2528 : DCHECK_NE(0, maps->size());
2529 722 : SetOperandAt(0, value);
2530 : // Use the object value for the dependency.
2531 722 : SetOperandAt(1, value);
2532 : set_representation(Representation::Tagged());
2533 : SetFlag(kUseGVN);
2534 : SetDependsOnFlag(kMaps);
2535 : SetDependsOnFlag(kElementsKind);
2536 722 : }
2537 :
2538 1635856 : HCheckMaps(HValue* value, const UniqueSet<Map>* maps, HValue* typecheck)
2539 : : HTemplateInstruction<2>(HType::HeapObject()),
2540 : maps_(maps),
2541 : bit_field_(HasMigrationTargetField::encode(false) |
2542 : IsStabilityCheckField::encode(false) |
2543 324458 : MapsAreStableField::encode(true)) {
2544 : DCHECK_NE(0, maps->size());
2545 324458 : SetOperandAt(0, value);
2546 : // Use the object value for the dependency if NULL is passed.
2547 324458 : SetOperandAt(1, typecheck ? typecheck : value);
2548 : set_representation(Representation::Tagged());
2549 : SetFlag(kUseGVN);
2550 : SetDependsOnFlag(kMaps);
2551 : SetDependsOnFlag(kElementsKind);
2552 1311398 : for (int i = 0; i < maps->size(); ++i) {
2553 : Handle<Map> map = maps->at(i).handle();
2554 331241 : if (map->is_migration_target()) {
2555 7898 : bit_field_ = HasMigrationTargetField::update(bit_field_, true);
2556 : }
2557 331241 : if (!map->is_stable()) {
2558 127362 : bit_field_ = MapsAreStableField::update(bit_field_, false);
2559 : }
2560 : }
2561 324458 : if (HasMigrationTarget()) SetChangesFlag(kNewSpacePromotion);
2562 324458 : }
2563 :
2564 : class HasMigrationTargetField : public BitField<bool, 0, 1> {};
2565 : class IsStabilityCheckField : public BitField<bool, 1, 1> {};
2566 : class MapsAreStableField : public BitField<bool, 2, 1> {};
2567 :
2568 : const UniqueSet<Map>* maps_;
2569 : uint32_t bit_field_;
2570 : };
2571 :
2572 :
2573 0 : class HCheckValue final : public HUnaryOperation {
2574 : public:
2575 203106 : static HCheckValue* New(Isolate* isolate, Zone* zone, HValue* context,
2576 : HValue* value, Handle<JSFunction> func) {
2577 : bool in_new_space = isolate->heap()->InNewSpace(*func);
2578 : // NOTE: We create an uninitialized Unique and initialize it later.
2579 : // This is because a JSFunction can move due to GC during graph creation.
2580 : Unique<JSFunction> target = Unique<JSFunction>::CreateUninitialized(func);
2581 : HCheckValue* check = new(zone) HCheckValue(value, target, in_new_space);
2582 203106 : return check;
2583 : }
2584 1824 : static HCheckValue* New(Isolate* isolate, Zone* zone, HValue* context,
2585 : HValue* value, Unique<HeapObject> target,
2586 : bool object_in_new_space) {
2587 3648 : return new(zone) HCheckValue(value, target, object_in_new_space);
2588 : }
2589 :
2590 202617 : void FinalizeUniqueness() override {
2591 202617 : object_ = Unique<HeapObject>(object_.handle());
2592 202617 : }
2593 :
2594 204282 : Representation RequiredInputRepresentation(int index) override {
2595 204282 : return Representation::Tagged();
2596 : }
2597 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
2598 :
2599 : HValue* Canonicalize() override;
2600 :
2601 : #ifdef DEBUG
2602 : void Verify() override;
2603 : #endif
2604 :
2605 : Unique<HeapObject> object() const { return object_; }
2606 : bool object_in_new_space() const { return object_in_new_space_; }
2607 :
2608 2189117 : DECLARE_CONCRETE_INSTRUCTION(CheckValue)
2609 :
2610 : protected:
2611 1204 : bool DataEquals(HValue* other) override {
2612 : HCheckValue* b = HCheckValue::cast(other);
2613 2408 : return object_ == b->object_;
2614 : }
2615 :
2616 : private:
2617 : HCheckValue(HValue* value, Unique<HeapObject> object,
2618 : bool object_in_new_space)
2619 : : HUnaryOperation(value, value->type()),
2620 : object_(object),
2621 204930 : object_in_new_space_(object_in_new_space) {
2622 : set_representation(Representation::Tagged());
2623 : SetFlag(kUseGVN);
2624 : }
2625 :
2626 : Unique<HeapObject> object_;
2627 : bool object_in_new_space_;
2628 : };
2629 :
2630 :
2631 0 : class HCheckInstanceType final : public HUnaryOperation {
2632 : public:
2633 : enum Check {
2634 : IS_JS_RECEIVER,
2635 : IS_JS_ARRAY,
2636 : IS_JS_FUNCTION,
2637 : IS_JS_DATE,
2638 : IS_STRING,
2639 : IS_INTERNALIZED_STRING,
2640 : LAST_INTERVAL_CHECK = IS_JS_DATE
2641 : };
2642 :
2643 190696 : DECLARE_INSTRUCTION_FACTORY_P2(HCheckInstanceType, HValue*, Check);
2644 :
2645 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
2646 :
2647 97171 : Representation RequiredInputRepresentation(int index) override {
2648 97171 : return Representation::Tagged();
2649 : }
2650 :
2651 89311 : HType CalculateInferredType() override {
2652 89311 : switch (check_) {
2653 : case IS_JS_RECEIVER: return HType::JSReceiver();
2654 : case IS_JS_ARRAY: return HType::JSArray();
2655 : case IS_JS_FUNCTION:
2656 : return HType::JSObject();
2657 : case IS_JS_DATE: return HType::JSObject();
2658 : case IS_STRING: return HType::String();
2659 : case IS_INTERNALIZED_STRING: return HType::String();
2660 : }
2661 0 : UNREACHABLE();
2662 : return HType::Tagged();
2663 : }
2664 :
2665 : HValue* Canonicalize() override;
2666 :
2667 50117 : bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
2668 : void GetCheckInterval(InstanceType* first, InstanceType* last);
2669 : void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);
2670 :
2671 : Check check() const { return check_; }
2672 :
2673 1470316 : DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)
2674 :
2675 : protected:
2676 : // TODO(ager): It could be nice to allow the ommision of instance
2677 : // type checks if we have already performed an instance type check
2678 : // with a larger range.
2679 19517 : bool DataEquals(HValue* other) override {
2680 : HCheckInstanceType* b = HCheckInstanceType::cast(other);
2681 19517 : return check_ == b->check_;
2682 : }
2683 :
2684 134690 : int RedefinedOperandIndex() override { return 0; }
2685 :
2686 : private:
2687 : const char* GetCheckName() const;
2688 :
2689 : HCheckInstanceType(HValue* value, Check check)
2690 95348 : : HUnaryOperation(value, HType::HeapObject()), check_(check) {
2691 : set_representation(Representation::Tagged());
2692 : SetFlag(kUseGVN);
2693 : }
2694 :
2695 : const Check check_;
2696 : };
2697 :
2698 :
2699 0 : class HCheckSmi final : public HUnaryOperation {
2700 : public:
2701 : DECLARE_INSTRUCTION_FACTORY_P1(HCheckSmi, HValue*);
2702 :
2703 0 : Representation RequiredInputRepresentation(int index) override {
2704 0 : return Representation::Tagged();
2705 : }
2706 :
2707 0 : HValue* Canonicalize() override {
2708 : HType value_type = value()->type();
2709 0 : if (value_type.IsSmi()) {
2710 : return NULL;
2711 : }
2712 0 : return this;
2713 : }
2714 :
2715 0 : DECLARE_CONCRETE_INSTRUCTION(CheckSmi)
2716 :
2717 : protected:
2718 0 : bool DataEquals(HValue* other) override { return true; }
2719 :
2720 : private:
2721 : explicit HCheckSmi(HValue* value) : HUnaryOperation(value, HType::Smi()) {
2722 : set_representation(Representation::Smi());
2723 : SetFlag(kUseGVN);
2724 : }
2725 : };
2726 :
2727 :
2728 0 : class HCheckArrayBufferNotNeutered final : public HUnaryOperation {
2729 : public:
2730 4032 : DECLARE_INSTRUCTION_FACTORY_P1(HCheckArrayBufferNotNeutered, HValue*);
2731 :
2732 0 : bool HasEscapingOperandAt(int index) override { return false; }
2733 4032 : Representation RequiredInputRepresentation(int index) override {
2734 4032 : return Representation::Tagged();
2735 : }
2736 :
2737 4032 : HType CalculateInferredType() override {
2738 4032 : if (value()->type().IsHeapObject()) return value()->type();
2739 : return HType::HeapObject();
2740 : }
2741 :
2742 63548 : DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered)
2743 :
2744 : protected:
2745 1599 : bool DataEquals(HValue* other) override { return true; }
2746 8763 : int RedefinedOperandIndex() override { return 0; }
2747 :
2748 : private:
2749 4032 : explicit HCheckArrayBufferNotNeutered(HValue* value)
2750 4032 : : HUnaryOperation(value) {
2751 : set_representation(Representation::Tagged());
2752 : SetFlag(kUseGVN);
2753 : SetDependsOnFlag(kCalls);
2754 4032 : }
2755 : };
2756 :
2757 :
2758 0 : class HCheckHeapObject final : public HUnaryOperation {
2759 : public:
2760 367018 : DECLARE_INSTRUCTION_FACTORY_P1(HCheckHeapObject, HValue*);
2761 :
2762 875 : bool HasEscapingOperandAt(int index) override { return false; }
2763 197461 : Representation RequiredInputRepresentation(int index) override {
2764 197461 : return Representation::Tagged();
2765 : }
2766 :
2767 181291 : HType CalculateInferredType() override {
2768 181291 : if (value()->type().IsHeapObject()) return value()->type();
2769 : return HType::HeapObject();
2770 : }
2771 :
2772 : #ifdef DEBUG
2773 : void Verify() override;
2774 : #endif
2775 :
2776 177200 : HValue* Canonicalize() override {
2777 177200 : return value()->type().IsHeapObject() ? NULL : this;
2778 : }
2779 :
2780 2902695 : DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject)
2781 :
2782 : protected:
2783 65383 : bool DataEquals(HValue* other) override { return true; }
2784 :
2785 : private:
2786 183509 : explicit HCheckHeapObject(HValue* value) : HUnaryOperation(value) {
2787 : set_representation(Representation::Tagged());
2788 : SetFlag(kUseGVN);
2789 : }
2790 : };
2791 :
2792 :
2793 0 : class HPhi final : public HValue {
2794 : public:
2795 696556 : HPhi(int merged_index, Zone* zone)
2796 696556 : : inputs_(2, zone), merged_index_(merged_index) {
2797 : DCHECK(merged_index >= 0 || merged_index == kInvalidMergedIndex);
2798 : SetFlag(kFlexibleRepresentation);
2799 696556 : }
2800 :
2801 : Representation RepresentationFromInputs() override;
2802 :
2803 : Range* InferRange(Zone* zone) override;
2804 : void InferRepresentation(HInferRepresentationPhase* h_infer) override;
2805 1276382 : Representation RequiredInputRepresentation(int index) override {
2806 1276382 : return representation();
2807 : }
2808 541302 : Representation KnownOptimalRepresentation() override {
2809 541302 : return representation();
2810 : }
2811 : HType CalculateInferredType() override;
2812 11417658 : int OperandCount() const override { return inputs_.length(); }
2813 25650671 : HValue* OperandAt(int index) const override { return inputs_[index]; }
2814 : HValue* GetRedundantReplacement();
2815 : void AddInput(HValue* value);
2816 : bool HasRealUses();
2817 :
2818 : bool IsReceiver() const { return merged_index_ == 0; }
2819 : bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; }
2820 :
2821 : SourcePosition position() const override;
2822 :
2823 : int merged_index() const { return merged_index_; }
2824 :
2825 : std::ostream& PrintTo(std::ostream& os) const override; // NOLINT
2826 :
2827 : #ifdef DEBUG
2828 : void Verify() override;
2829 : #endif
2830 :
2831 : void InitRealUses(int id);
2832 : void AddNonPhiUsesFrom(HPhi* other);
2833 :
2834 : Representation representation_from_indirect_uses() const {
2835 : return representation_from_indirect_uses_;
2836 : }
2837 :
2838 : bool has_type_feedback_from_uses() const {
2839 : return has_type_feedback_from_uses_;
2840 : }
2841 :
2842 : int phi_id() { return phi_id_; }
2843 :
2844 155 : static HPhi* cast(HValue* value) {
2845 : DCHECK(value->IsPhi());
2846 155 : return reinterpret_cast<HPhi*>(value);
2847 : }
2848 23374135 : Opcode opcode() const override { return HValue::kPhi; }
2849 :
2850 : void SimplifyConstantInputs();
2851 :
2852 : // Marker value representing an invalid merge index.
2853 : static const int kInvalidMergedIndex = -1;
2854 :
2855 : protected:
2856 : void DeleteFromGraph() override;
2857 2055364 : void InternalSetOperandAt(int index, HValue* value) override {
2858 4110728 : inputs_[index] = value;
2859 2055364 : }
2860 :
2861 : private:
2862 : Representation representation_from_non_phi_uses() const {
2863 : return representation_from_non_phi_uses_;
2864 : }
2865 :
2866 : ZoneList<HValue*> inputs_;
2867 : int merged_index_ = 0;
2868 :
2869 : int phi_id_ = -1;
2870 :
2871 : Representation representation_from_indirect_uses_ = Representation::None();
2872 : Representation representation_from_non_phi_uses_ = Representation::None();
2873 : bool has_type_feedback_from_uses_ = false;
2874 :
2875 224 : bool IsDeletable() const override { return !IsReceiver(); }
2876 : };
2877 :
2878 :
2879 : // Common base class for HArgumentsObject and HCapturedObject.
2880 0 : class HDematerializedObject : public HInstruction {
2881 : public:
2882 764542 : HDematerializedObject(int count, Zone* zone) : values_(count, zone) {}
2883 :
2884 86150 : int OperandCount() const final { return values_.length(); }
2885 2599541 : HValue* OperandAt(int index) const final { return values_[index]; }
2886 :
2887 394 : bool HasEscapingOperandAt(int index) final { return false; }
2888 811050 : Representation RequiredInputRepresentation(int index) final {
2889 811050 : return Representation::None();
2890 : }
2891 :
2892 : protected:
2893 960181 : void InternalSetOperandAt(int index, HValue* value) final {
2894 1920362 : values_[index] = value;
2895 960181 : }
2896 :
2897 : // List of values tracked by this marker.
2898 : ZoneList<HValue*> values_;
2899 : };
2900 :
2901 :
2902 0 : class HArgumentsObject final : public HDematerializedObject {
2903 : public:
2904 371310 : static HArgumentsObject* New(Isolate* isolate, Zone* zone, HValue* context,
2905 : int count) {
2906 371311 : return new(zone) HArgumentsObject(count, zone);
2907 : }
2908 :
2909 : // The values contain a list of all elements in the arguments object
2910 : // including the receiver object, which is skipped when materializing.
2911 : const ZoneList<HValue*>* arguments_values() const { return &values_; }
2912 : int arguments_count() const { return values_.length(); }
2913 :
2914 726799 : void AddArgument(HValue* argument, Zone* zone) {
2915 : values_.Add(NULL, zone); // Resize list.
2916 726800 : SetOperandAt(values_.length() - 1, argument);
2917 726800 : }
2918 :
2919 5233886 : DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
2920 :
2921 : private:
2922 : HArgumentsObject(int count, Zone* zone)
2923 371310 : : HDematerializedObject(count, zone) {
2924 : set_representation(Representation::Tagged());
2925 : SetFlag(kIsArguments);
2926 : }
2927 : };
2928 :
2929 :
2930 0 : class HCapturedObject final : public HDematerializedObject {
2931 : public:
2932 10961 : HCapturedObject(int length, int id, Zone* zone)
2933 10961 : : HDematerializedObject(length, zone), capture_id_(id) {
2934 : set_representation(Representation::Tagged());
2935 10961 : values_.AddBlock(NULL, length, zone); // Resize list.
2936 10961 : }
2937 :
2938 : // The values contain a list of all in-object properties inside the
2939 : // captured object and is index by field index. Properties in the
2940 : // properties or elements backing store are not tracked here.
2941 : const ZoneList<HValue*>* values() const { return &values_; }
2942 : int length() const { return values_.length(); }
2943 : int capture_id() const { return capture_id_; }
2944 :
2945 : // Shortcut for the map value of this captured object.
2946 1390 : HValue* map_value() const { return values()->first(); }
2947 :
2948 : void ReuseSideEffectsFromStore(HInstruction* store) {
2949 : DCHECK(store->HasObservableSideEffects());
2950 : DCHECK(store->IsStoreNamedField());
2951 : changes_flags_.Add(store->ChangesFlags());
2952 : }
2953 :
2954 : // Replay effects of this instruction on the given environment.
2955 : void ReplayEnvironment(HEnvironment* env);
2956 :
2957 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
2958 :
2959 387528 : DECLARE_CONCRETE_INSTRUCTION(CapturedObject)
2960 :
2961 : private:
2962 : int capture_id_;
2963 :
2964 : // Note that we cannot DCE captured objects as they are used to replay
2965 : // the environment. This method is here as an explicit reminder.
2966 : // TODO(mstarzinger): Turn HSimulates into full snapshots maybe?
2967 59 : bool IsDeletable() const final { return false; }
2968 : };
2969 :
2970 :
2971 0 : class HConstant final : public HTemplateInstruction<0> {
2972 : public:
2973 : enum Special { kHoleNaN };
2974 :
2975 128 : DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Special);
2976 4428199 : DECLARE_INSTRUCTION_FACTORY_P1(HConstant, int32_t);
2977 7988 : DECLARE_INSTRUCTION_FACTORY_P2(HConstant, int32_t, Representation);
2978 974 : DECLARE_INSTRUCTION_FACTORY_P1(HConstant, double);
2979 9240594 : DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Handle<Object>);
2980 22410 : DECLARE_INSTRUCTION_FACTORY_P1(HConstant, ExternalReference);
2981 :
2982 : static HConstant* CreateAndInsertAfter(Isolate* isolate, Zone* zone,
2983 : HValue* context, int32_t value,
2984 : Representation representation,
2985 : HInstruction* instruction) {
2986 : return instruction->Append(
2987 : HConstant::New(isolate, zone, context, value, representation));
2988 : }
2989 :
2990 338104 : Handle<Map> GetMonomorphicJSObjectMap() override {
2991 : Handle<Object> object = object_.handle();
2992 676208 : if (!object.is_null() && object->IsHeapObject()) {
2993 : return v8::internal::handle(HeapObject::cast(*object)->map());
2994 : }
2995 4804 : return Handle<Map>();
2996 : }
2997 :
2998 : static HConstant* CreateAndInsertBefore(Isolate* isolate, Zone* zone,
2999 : HValue* context, int32_t value,
3000 : Representation representation,
3001 : HInstruction* instruction) {
3002 : return instruction->Prepend(
3003 2829 : HConstant::New(isolate, zone, context, value, representation));
3004 : }
3005 :
3006 14 : static HConstant* CreateAndInsertBefore(Zone* zone,
3007 : Unique<Map> map,
3008 : bool map_is_stable,
3009 : HInstruction* instruction) {
3010 : return instruction->Prepend(new(zone) HConstant(
3011 : map, Unique<Map>(Handle<Map>::null()), map_is_stable,
3012 : Representation::Tagged(), HType::HeapObject(), true,
3013 42 : false, false, MAP_TYPE));
3014 : }
3015 :
3016 : static HConstant* CreateAndInsertAfter(Zone* zone,
3017 : Unique<Map> map,
3018 : bool map_is_stable,
3019 : HInstruction* instruction) {
3020 : return instruction->Append(new(zone) HConstant(
3021 : map, Unique<Map>(Handle<Map>::null()), map_is_stable,
3022 : Representation::Tagged(), HType::HeapObject(), true,
3023 : false, false, MAP_TYPE));
3024 : }
3025 :
3026 18781481 : Handle<Object> handle(Isolate* isolate) {
3027 18781481 : if (object_.handle().is_null()) {
3028 : // Default arguments to is_not_in_new_space depend on this heap number
3029 : // to be tenured so that it's guaranteed not to be located in new space.
3030 : object_ = Unique<Object>::CreateUninitialized(
3031 175420 : isolate->factory()->NewNumber(double_value_, TENURED));
3032 : }
3033 : AllowDeferredHandleDereference smi_check;
3034 : DCHECK(HasInteger32Value() || !object_.handle()->IsSmi());
3035 18781481 : return object_.handle();
3036 : }
3037 :
3038 556 : bool IsSpecialDouble() const {
3039 1112 : return HasDoubleValue() &&
3040 1100 : (bit_cast<int64_t>(double_value_) == bit_cast<int64_t>(-0.0) ||
3041 1100 : std::isnan(double_value_));
3042 : }
3043 :
3044 : bool NotInNewSpace() const {
3045 : return IsNotInNewSpaceField::decode(bit_field_);
3046 : }
3047 :
3048 : bool ImmortalImmovable() const;
3049 :
3050 8008276 : bool IsCell() const {
3051 : InstanceType instance_type = GetInstanceType();
3052 : return instance_type == CELL_TYPE;
3053 : }
3054 :
3055 0 : Representation RequiredInputRepresentation(int index) override {
3056 0 : return Representation::None();
3057 : }
3058 :
3059 206460 : Representation KnownOptimalRepresentation() override {
3060 : if (HasSmiValue() && SmiValuesAre31Bits()) return Representation::Smi();
3061 206460 : if (HasInteger32Value()) return Representation::Integer32();
3062 124558 : if (HasNumberValue()) return Representation::Double();
3063 116953 : if (HasExternalReferenceValue()) return Representation::External();
3064 : return Representation::Tagged();
3065 : }
3066 :
3067 : bool EmitAtUses() override;
3068 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
3069 : HConstant* CopyToRepresentation(Representation r, Zone* zone) const;
3070 : Maybe<HConstant*> CopyToTruncatedInt32(Zone* zone);
3071 : Maybe<HConstant*> CopyToTruncatedNumber(Isolate* isolate, Zone* zone);
3072 : bool HasInteger32Value() const {
3073 : return HasInt32ValueField::decode(bit_field_);
3074 : }
3075 : int32_t Integer32Value() const {
3076 : DCHECK(HasInteger32Value());
3077 : return int32_value_;
3078 : }
3079 : bool HasSmiValue() const { return HasSmiValueField::decode(bit_field_); }
3080 : bool HasDoubleValue() const {
3081 : return HasDoubleValueField::decode(bit_field_);
3082 : }
3083 : double DoubleValue() const {
3084 : DCHECK(HasDoubleValue());
3085 : return double_value_;
3086 : }
3087 : uint64_t DoubleValueAsBits() const {
3088 : DCHECK(HasDoubleValue());
3089 213489 : return bit_cast<uint64_t>(double_value_);
3090 : }
3091 : bool IsTheHole() const {
3092 : if (HasDoubleValue() && DoubleValueAsBits() == kHoleNanInt64) {
3093 : return true;
3094 : }
3095 : return object_.IsInitialized() &&
3096 : object_.IsKnownGlobal(isolate()->heap()->the_hole_value());
3097 : }
3098 138066 : bool HasNumberValue() const { return HasDoubleValue(); }
3099 : int32_t NumberValueAsInteger32() const {
3100 : DCHECK(HasNumberValue());
3101 : // Irrespective of whether a numeric HConstant can be safely
3102 : // represented as an int32, we store the (in some cases lossy)
3103 : // representation of the number in int32_value_.
3104 : return int32_value_;
3105 : }
3106 : bool HasStringValue() const {
3107 136715 : if (HasNumberValue()) return false;
3108 : DCHECK(!object_.handle().is_null());
3109 130573 : return GetInstanceType() < FIRST_NONSTRING_TYPE;
3110 : }
3111 : Handle<String> StringValue() const {
3112 : DCHECK(HasStringValue());
3113 : return Handle<String>::cast(object_.handle());
3114 : }
3115 8522 : bool HasInternalizedStringValue() const {
3116 17042 : return HasStringValue() && StringShape(GetInstanceType()).IsInternalized();
3117 : }
3118 :
3119 : bool HasExternalReferenceValue() const {
3120 : return HasExternalReferenceValueField::decode(bit_field_);
3121 : }
3122 : ExternalReference ExternalReferenceValue() const {
3123 : return external_reference_value_;
3124 : }
3125 :
3126 : bool HasBooleanValue() const { return type_.IsBoolean(); }
3127 : bool BooleanValue() const { return BooleanValueField::decode(bit_field_); }
3128 : bool IsCallable() const { return IsCallableField::decode(bit_field_); }
3129 : bool IsUndetectable() const {
3130 : return IsUndetectableField::decode(bit_field_);
3131 : }
3132 : InstanceType GetInstanceType() const {
3133 : return InstanceTypeField::decode(bit_field_);
3134 : }
3135 :
3136 : bool HasMapValue() const { return GetInstanceType() == MAP_TYPE; }
3137 : Unique<Map> MapValue() const {
3138 : DCHECK(HasMapValue());
3139 : return Unique<Map>::cast(GetUnique());
3140 : }
3141 : bool HasStableMapValue() const {
3142 : DCHECK(HasMapValue() || !HasStableMapValueField::decode(bit_field_));
3143 : return HasStableMapValueField::decode(bit_field_);
3144 : }
3145 :
3146 184373 : bool HasObjectMap() const { return !object_map_.IsNull(); }
3147 : Unique<Map> ObjectMap() const {
3148 : DCHECK(HasObjectMap());
3149 : return object_map_;
3150 : }
3151 :
3152 18304577 : intptr_t Hashcode() override {
3153 18304577 : if (HasInteger32Value()) {
3154 7413576 : return static_cast<intptr_t>(int32_value_);
3155 10891001 : } else if (HasDoubleValue()) {
3156 : uint64_t bits = DoubleValueAsBits();
3157 : if (sizeof(bits) > sizeof(intptr_t)) {
3158 : bits ^= (bits >> 32);
3159 : }
3160 170493 : return static_cast<intptr_t>(bits);
3161 10720508 : } else if (HasExternalReferenceValue()) {
3162 29105 : return reinterpret_cast<intptr_t>(external_reference_value_.address());
3163 : } else {
3164 : DCHECK(!object_.handle().is_null());
3165 21382806 : return object_.Hashcode();
3166 : }
3167 : }
3168 :
3169 7056340 : void FinalizeUniqueness() override {
3170 11610327 : if (!HasDoubleValue() && !HasExternalReferenceValue()) {
3171 : DCHECK(!object_.handle().is_null());
3172 4542833 : object_ = Unique<Object>(object_.handle());
3173 : }
3174 7056340 : }
3175 :
3176 : Unique<Object> GetUnique() const {
3177 : return object_;
3178 : }
3179 :
3180 : bool EqualsUnique(Unique<Object> other) const {
3181 164491 : return object_.IsInitialized() && object_ == other;
3182 : }
3183 :
3184 5716156 : bool DataEquals(HValue* other) override {
3185 5716156 : HConstant* other_constant = HConstant::cast(other);
3186 5716156 : if (HasInteger32Value()) {
3187 2062343 : return other_constant->HasInteger32Value() &&
3188 2062343 : int32_value_ == other_constant->int32_value_;
3189 4647148 : } else if (HasDoubleValue()) {
3190 1240132 : return other_constant->HasDoubleValue() &&
3191 : std::memcmp(&double_value_, &other_constant->double_value_,
3192 1240132 : sizeof(double_value_)) == 0;
3193 4027082 : } else if (HasExternalReferenceValue()) {
3194 5020 : return other_constant->HasExternalReferenceValue() &&
3195 2510 : external_reference_value_ ==
3196 2510 : other_constant->external_reference_value_;
3197 : } else {
3198 8049142 : if (other_constant->HasInteger32Value() ||
3199 8049142 : other_constant->HasDoubleValue() ||
3200 : other_constant->HasExternalReferenceValue()) {
3201 : return false;
3202 : }
3203 : DCHECK(!object_.handle().is_null());
3204 8049140 : return other_constant->object_ == object_;
3205 : }
3206 : }
3207 :
3208 : #ifdef DEBUG
3209 : void Verify() override {}
3210 : #endif
3211 :
3212 229068921 : DECLARE_CONCRETE_INSTRUCTION(Constant)
3213 :
3214 : protected:
3215 : Range* InferRange(Zone* zone) override;
3216 :
3217 : private:
3218 : friend class HGraph;
3219 : explicit HConstant(Special special);
3220 : explicit HConstant(Handle<Object> handle,
3221 : Representation r = Representation::None());
3222 : HConstant(int32_t value,
3223 : Representation r = Representation::None(),
3224 : bool is_not_in_new_space = true,
3225 : Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
3226 : HConstant(double value,
3227 : Representation r = Representation::None(),
3228 : bool is_not_in_new_space = true,
3229 : Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
3230 : HConstant(Unique<Object> object,
3231 : Unique<Map> object_map,
3232 : bool has_stable_map_value,
3233 : Representation r,
3234 : HType type,
3235 : bool is_not_in_new_space,
3236 : bool boolean_value,
3237 : bool is_undetectable,
3238 : InstanceType instance_type);
3239 :
3240 : explicit HConstant(ExternalReference reference);
3241 :
3242 : void Initialize(Representation r);
3243 :
3244 3967 : bool IsDeletable() const override { return true; }
3245 :
3246 : // If object_ is a map, this indicates whether the map is stable.
3247 : class HasStableMapValueField : public BitField<bool, 0, 1> {};
3248 :
3249 : // We store the HConstant in the most specific form safely possible.
3250 : // These flags tell us if the respective member fields hold valid, safe
3251 : // representations of the constant. More specific flags imply more general
3252 : // flags, but not the converse (i.e. smi => int32 => double).
3253 : class HasSmiValueField : public BitField<bool, 1, 1> {};
3254 : class HasInt32ValueField : public BitField<bool, 2, 1> {};
3255 : class HasDoubleValueField : public BitField<bool, 3, 1> {};
3256 :
3257 : class HasExternalReferenceValueField : public BitField<bool, 4, 1> {};
3258 : class IsNotInNewSpaceField : public BitField<bool, 5, 1> {};
3259 : class BooleanValueField : public BitField<bool, 6, 1> {};
3260 : class IsUndetectableField : public BitField<bool, 7, 1> {};
3261 : class IsCallableField : public BitField<bool, 8, 1> {};
3262 :
3263 : static const InstanceType kUnknownInstanceType = FILLER_TYPE;
3264 : class InstanceTypeField : public BitField<InstanceType, 16, 8> {};
3265 :
3266 : // If this is a numerical constant, object_ either points to the
3267 : // HeapObject the constant originated from or is null. If the
3268 : // constant is non-numeric, object_ always points to a valid
3269 : // constant HeapObject.
3270 : Unique<Object> object_;
3271 :
3272 : // If object_ is a heap object, this points to the stable map of the object.
3273 : Unique<Map> object_map_;
3274 :
3275 : uint32_t bit_field_;
3276 :
3277 : int32_t int32_value_;
3278 : double double_value_;
3279 : ExternalReference external_reference_value_;
3280 : };
3281 :
3282 :
3283 0 : class HBinaryOperation : public HTemplateInstruction<3> {
3284 : public:
3285 944089 : HBinaryOperation(HValue* context, HValue* left, HValue* right,
3286 : HType type = HType::Tagged())
3287 : : HTemplateInstruction<3>(type),
3288 2832267 : observed_output_representation_(Representation::None()) {
3289 : DCHECK(left != NULL && right != NULL);
3290 944089 : SetOperandAt(0, context);
3291 944089 : SetOperandAt(1, left);
3292 944089 : SetOperandAt(2, right);
3293 944089 : observed_input_representation_[0] = Representation::None();
3294 944089 : observed_input_representation_[1] = Representation::None();
3295 944089 : }
3296 :
3297 : HValue* context() const { return OperandAt(0); }
3298 : HValue* left() const { return OperandAt(1); }
3299 : HValue* right() const { return OperandAt(2); }
3300 :
3301 : // True if switching left and right operands likely generates better code.
3302 826163 : bool AreOperandsBetterSwitched() {
3303 826163 : if (!IsCommutative()) return false;
3304 :
3305 : // Constant operands are better off on the right, they can be inlined in
3306 : // many situations on most platforms.
3307 772707 : if (left()->IsConstant()) return true;
3308 714300 : if (right()->IsConstant()) return false;
3309 :
3310 : // Otherwise, if there is only one use of the right operand, it would be
3311 : // better off on the left for platforms that only have 2-arg arithmetic
3312 : // ops (e.g ia32, x64) that clobber the left operand.
3313 400504 : return right()->HasOneUse();
3314 : }
3315 :
3316 : HValue* BetterLeftOperand() {
3317 498399 : return AreOperandsBetterSwitched() ? right() : left();
3318 : }
3319 :
3320 : HValue* BetterRightOperand() {
3321 327767 : return AreOperandsBetterSwitched() ? left() : right();
3322 : }
3323 :
3324 : void set_observed_input_representation(int index, Representation rep) {
3325 : DCHECK(index >= 1 && index <= 2);
3326 709224 : observed_input_representation_[index - 1] = rep;
3327 : }
3328 :
3329 260976 : virtual void initialize_output_representation(Representation observed) {
3330 336379 : observed_output_representation_ = observed;
3331 260976 : }
3332 :
3333 1911676 : Representation observed_input_representation(int index) override {
3334 2555912 : if (index == 0) return Representation::Tagged();
3335 2532644 : return observed_input_representation_[index - 1];
3336 : }
3337 :
3338 2036939 : void UpdateRepresentation(Representation new_rep,
3339 : HInferRepresentationPhase* h_infer,
3340 : const char* reason) override {
3341 2036939 : Representation rep = !FLAG_smi_binop && new_rep.IsSmi()
3342 2036939 : ? Representation::Integer32() : new_rep;
3343 2036939 : HValue::UpdateRepresentation(rep, h_infer, reason);
3344 2036947 : }
3345 :
3346 : void InferRepresentation(HInferRepresentationPhase* h_infer) override;
3347 : Representation RepresentationFromInputs() override;
3348 : Representation RepresentationFromOutput();
3349 : void AssumeRepresentation(Representation r) override;
3350 :
3351 48902 : virtual bool IsCommutative() const { return false; }
3352 :
3353 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
3354 :
3355 990717 : Representation RequiredInputRepresentation(int index) override {
3356 2136466 : if (index == 0) return Representation::Tagged();
3357 : return representation();
3358 : }
3359 :
3360 8223 : bool RightIsPowerOf2() {
3361 8223 : if (!right()->IsInteger32Constant()) return false;
3362 7296 : int32_t value = right()->GetInteger32Constant();
3363 7296 : if (value < 0) {
3364 6540 : return base::bits::IsPowerOfTwo32(static_cast<uint32_t>(-value));
3365 : }
3366 8052 : return base::bits::IsPowerOfTwo32(static_cast<uint32_t>(value));
3367 : }
3368 :
3369 336862 : DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation)
3370 :
3371 : private:
3372 : bool IgnoreObservedOutputRepresentation(Representation current_rep);
3373 :
3374 : Representation observed_input_representation_[2];
3375 : Representation observed_output_representation_;
3376 : };
3377 :
3378 :
3379 0 : class HWrapReceiver final : public HTemplateInstruction<2> {
3380 : public:
3381 4956 : DECLARE_INSTRUCTION_FACTORY_P2(HWrapReceiver, HValue*, HValue*);
3382 :
3383 0 : bool DataEquals(HValue* other) override { return true; }
3384 :
3385 10886 : Representation RequiredInputRepresentation(int index) override {
3386 10886 : return Representation::Tagged();
3387 : }
3388 :
3389 : HValue* receiver() const { return OperandAt(0); }
3390 : HValue* function() const { return OperandAt(1); }
3391 :
3392 : HValue* Canonicalize() override;
3393 :
3394 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
3395 : bool known_function() const { return known_function_; }
3396 :
3397 125500 : DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
3398 :
3399 : private:
3400 9912 : HWrapReceiver(HValue* receiver, HValue* function) {
3401 4956 : known_function_ = function->IsConstant() &&
3402 4956 : HConstant::cast(function)->handle(function->isolate())->IsJSFunction();
3403 : set_representation(Representation::Tagged());
3404 4956 : SetOperandAt(0, receiver);
3405 4956 : SetOperandAt(1, function);
3406 : SetFlag(kUseGVN);
3407 4956 : }
3408 :
3409 : bool known_function_;
3410 : };
3411 :
3412 :
3413 0 : class HApplyArguments final : public HTemplateInstruction<4> {
3414 : public:
3415 136 : DECLARE_INSTRUCTION_FACTORY_P5(HApplyArguments, HValue*, HValue*, HValue*,
3416 : HValue*, TailCallMode);
3417 :
3418 550 : Representation RequiredInputRepresentation(int index) override {
3419 : // The length is untagged, all other inputs are tagged.
3420 : return (index == 2)
3421 : ? Representation::Integer32()
3422 550 : : Representation::Tagged();
3423 : }
3424 :
3425 : HValue* function() { return OperandAt(0); }
3426 : HValue* receiver() { return OperandAt(1); }
3427 : HValue* length() { return OperandAt(2); }
3428 : HValue* elements() { return OperandAt(3); }
3429 :
3430 : TailCallMode tail_call_mode() const {
3431 : return TailCallModeField::decode(bit_field_);
3432 : }
3433 :
3434 10985 : DECLARE_CONCRETE_INSTRUCTION(ApplyArguments)
3435 :
3436 : private:
3437 136 : HApplyArguments(HValue* function, HValue* receiver, HValue* length,
3438 : HValue* elements, TailCallMode tail_call_mode)
3439 136 : : bit_field_(TailCallModeField::encode(tail_call_mode)) {
3440 : set_representation(Representation::Tagged());
3441 136 : SetOperandAt(0, function);
3442 136 : SetOperandAt(1, receiver);
3443 136 : SetOperandAt(2, length);
3444 136 : SetOperandAt(3, elements);
3445 : SetAllSideEffects();
3446 136 : }
3447 :
3448 : class TailCallModeField : public BitField<TailCallMode, 0, 1> {};
3449 : uint32_t bit_field_;
3450 : };
3451 :
3452 :
3453 0 : class HArgumentsElements final : public HTemplateInstruction<0> {
3454 : public:
3455 2376 : DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsElements, bool);
3456 : DECLARE_INSTRUCTION_FACTORY_P2(HArgumentsElements, bool, bool);
3457 :
3458 19318 : DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
3459 :
3460 0 : Representation RequiredInputRepresentation(int index) override {
3461 0 : return Representation::None();
3462 : }
3463 :
3464 : bool from_inlined() const { return from_inlined_; }
3465 : bool arguments_adaptor() const { return arguments_adaptor_; }
3466 :
3467 : protected:
3468 336 : bool DataEquals(HValue* other) override { return true; }
3469 :
3470 : private:
3471 : explicit HArgumentsElements(bool from_inlined, bool arguments_adaptor = true)
3472 1188 : : from_inlined_(from_inlined), arguments_adaptor_(arguments_adaptor) {
3473 : // The value produced by this instruction is a pointer into the stack
3474 : // that looks as if it was a smi because of alignment.
3475 : set_representation(Representation::Tagged());
3476 : SetFlag(kUseGVN);
3477 : }
3478 :
3479 0 : bool IsDeletable() const override { return true; }
3480 :
3481 : bool from_inlined_;
3482 : bool arguments_adaptor_;
3483 : };
3484 :
3485 :
3486 0 : class HArgumentsLength final : public HUnaryOperation {
3487 : public:
3488 1912 : DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsLength, HValue*);
3489 :
3490 919 : Representation RequiredInputRepresentation(int index) override {
3491 919 : return Representation::Tagged();
3492 : }
3493 :
3494 31386 : DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)
3495 :
3496 : protected:
3497 336 : bool DataEquals(HValue* other) override { return true; }
3498 :
3499 : private:
3500 956 : explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
3501 : set_representation(Representation::Integer32());
3502 : SetFlag(kUseGVN);
3503 : }
3504 :
3505 0 : bool IsDeletable() const override { return true; }
3506 : };
3507 :
3508 :
3509 0 : class HAccessArgumentsAt final : public HTemplateInstruction<3> {
3510 : public:
3511 715 : DECLARE_INSTRUCTION_FACTORY_P3(HAccessArgumentsAt, HValue*, HValue*, HValue*);
3512 :
3513 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
3514 :
3515 2124 : Representation RequiredInputRepresentation(int index) override {
3516 : // The arguments elements is considered tagged.
3517 : return index == 0
3518 : ? Representation::Tagged()
3519 2124 : : Representation::Integer32();
3520 : }
3521 :
3522 : HValue* arguments() const { return OperandAt(0); }
3523 : HValue* length() const { return OperandAt(1); }
3524 : HValue* index() const { return OperandAt(2); }
3525 :
3526 40405 : DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)
3527 :
3528 : private:
3529 1430 : HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
3530 : set_representation(Representation::Tagged());
3531 : SetFlag(kUseGVN);
3532 715 : SetOperandAt(0, arguments);
3533 715 : SetOperandAt(1, length);
3534 715 : SetOperandAt(2, index);
3535 715 : }
3536 :
3537 18 : bool DataEquals(HValue* other) override { return true; }
3538 : };
3539 :
3540 :
3541 0 : class HBoundsCheck final : public HTemplateInstruction<2> {
3542 : public:
3543 41190 : DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*);
3544 :
3545 : bool skip_check() const { return skip_check_; }
3546 : void set_skip_check() { skip_check_ = true; }
3547 :
3548 : HValue* base() const { return base_; }
3549 : int offset() const { return offset_; }
3550 : int scale() const { return scale_; }
3551 :
3552 93386 : Representation RequiredInputRepresentation(int index) override {
3553 93386 : return representation();
3554 : }
3555 :
3556 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
3557 : void InferRepresentation(HInferRepresentationPhase* h_infer) override;
3558 :
3559 : HValue* index() const { return OperandAt(0); }
3560 : HValue* length() const { return OperandAt(1); }
3561 : bool allow_equality() const { return allow_equality_; }
3562 : void set_allow_equality(bool v) { allow_equality_ = v; }
3563 :
3564 90940 : int RedefinedOperandIndex() override { return 0; }
3565 33118 : bool IsPurelyInformativeDefinition() override { return skip_check(); }
3566 :
3567 746752 : DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
3568 :
3569 : protected:
3570 : Range* InferRange(Zone* zone) override;
3571 :
3572 1264 : bool DataEquals(HValue* other) override { return true; }
3573 : bool skip_check_;
3574 : HValue* base_;
3575 : int offset_;
3576 : int scale_;
3577 : bool allow_equality_;
3578 :
3579 : private:
3580 : // Normally HBoundsCheck should be created using the
3581 : // HGraphBuilder::AddBoundsCheck() helper.
3582 : // However when building stubs, where we know that the arguments are Int32,
3583 : // it makes sense to invoke this constructor directly.
3584 41190 : HBoundsCheck(HValue* index, HValue* length)
3585 : : skip_check_(false),
3586 : base_(NULL), offset_(0), scale_(0),
3587 41190 : allow_equality_(false) {
3588 41190 : SetOperandAt(0, index);
3589 41190 : SetOperandAt(1, length);
3590 : SetFlag(kFlexibleRepresentation);
3591 : SetFlag(kUseGVN);
3592 41190 : }
3593 :
3594 12 : bool IsDeletable() const override { return skip_check() && !FLAG_debug_code; }
3595 : };
3596 :
3597 :
3598 0 : class HBitwiseBinaryOperation : public HBinaryOperation {
3599 : public:
3600 180784 : HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right,
3601 : HType type = HType::TaggedNumber())
3602 180784 : : HBinaryOperation(context, left, right, type) {
3603 : SetFlag(kFlexibleRepresentation);
3604 : SetFlag(kTruncatingToInt32);
3605 : SetFlag(kTruncatingToNumber);
3606 : SetAllSideEffects();
3607 180784 : }
3608 :
3609 167654 : void RepresentationChanged(Representation to) override {
3610 342762 : if (to.IsTagged() &&
3611 1628 : (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
3612 : SetAllSideEffects();
3613 : ClearFlag(kUseGVN);
3614 : } else {
3615 : ClearAllSideEffects();
3616 : SetFlag(kUseGVN);
3617 : }
3618 167654 : if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
3619 167654 : }
3620 :
3621 416826 : void UpdateRepresentation(Representation new_rep,
3622 : HInferRepresentationPhase* h_infer,
3623 : const char* reason) override {
3624 : // We only generate either int32 or generic tagged bitwise operations.
3625 564270 : if (new_rep.IsDouble()) new_rep = Representation::Integer32();
3626 564270 : HBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
3627 416826 : }
3628 :
3629 644236 : Representation observed_input_representation(int index) override {
3630 : Representation r = HBinaryOperation::observed_input_representation(index);
3631 644236 : if (r.IsDouble()) return Representation::Integer32();
3632 601850 : return r;
3633 : }
3634 :
3635 75403 : void initialize_output_representation(Representation observed) override {
3636 75403 : if (observed.IsDouble()) observed = Representation::Integer32();
3637 : HBinaryOperation::initialize_output_representation(observed);
3638 75403 : }
3639 :
3640 0 : DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
3641 :
3642 : private:
3643 160 : bool IsDeletable() const override { return true; }
3644 : };
3645 :
3646 :
3647 0 : class HMathFloorOfDiv final : public HBinaryOperation {
3648 : public:
3649 2600 : DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HMathFloorOfDiv,
3650 : HValue*,
3651 : HValue*);
3652 :
3653 48925 : DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv)
3654 :
3655 : protected:
3656 0 : bool DataEquals(HValue* other) override { return true; }
3657 :
3658 : private:
3659 2600 : HMathFloorOfDiv(HValue* context, HValue* left, HValue* right)
3660 2600 : : HBinaryOperation(context, left, right) {
3661 : set_representation(Representation::Integer32());
3662 : SetFlag(kUseGVN);
3663 : SetFlag(kCanOverflow);
3664 : SetFlag(kCanBeDivByZero);
3665 : SetFlag(kLeftCanBeMinInt);
3666 : SetFlag(kLeftCanBeNegative);
3667 : SetFlag(kLeftCanBePositive);
3668 : SetFlag(kTruncatingToNumber);
3669 2600 : }
3670 :
3671 : Range* InferRange(Zone* zone) override;
3672 :
3673 0 : bool IsDeletable() const override { return true; }
3674 : };
3675 :
3676 :
3677 0 : class HArithmeticBinaryOperation : public HBinaryOperation {
3678 : public:
3679 406012 : HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right,
3680 : HType type = HType::TaggedNumber())
3681 406012 : : HBinaryOperation(context, left, right, type) {
3682 : SetAllSideEffects();
3683 : SetFlag(kFlexibleRepresentation);
3684 : SetFlag(kTruncatingToNumber);
3685 406012 : }
3686 :
3687 133448 : void RepresentationChanged(Representation to) override {
3688 305306 : if (to.IsTagged() &&
3689 31797 : (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
3690 : SetAllSideEffects();
3691 : ClearFlag(kUseGVN);
3692 : } else {
3693 : ClearAllSideEffects();
3694 : SetFlag(kUseGVN);
3695 : }
3696 133448 : if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
3697 133448 : }
3698 :
3699 399046 : DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)
3700 :
3701 : private:
3702 149 : bool IsDeletable() const override { return true; }
3703 : };
3704 :
3705 :
3706 0 : class HCompareGeneric final : public HBinaryOperation {
3707 : public:
3708 327836 : static HCompareGeneric* New(Isolate* isolate, Zone* zone, HValue* context,
3709 : HValue* left, HValue* right, Token::Value token) {
3710 327836 : return new (zone) HCompareGeneric(context, left, right, token);
3711 : }
3712 :
3713 996826 : Representation RequiredInputRepresentation(int index) override {
3714 : return index == 0
3715 : ? Representation::Tagged()
3716 996826 : : representation();
3717 : }
3718 :
3719 : Token::Value token() const { return token_; }
3720 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
3721 :
3722 6989920 : DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
3723 :
3724 : private:
3725 : HCompareGeneric(HValue* context, HValue* left, HValue* right,
3726 : Token::Value token)
3727 : : HBinaryOperation(context, left, right, HType::Boolean()),
3728 327836 : token_(token) {
3729 : DCHECK(Token::IsCompareOp(token));
3730 : set_representation(Representation::Tagged());
3731 : SetAllSideEffects();
3732 : }
3733 :
3734 : Token::Value token_;
3735 : };
3736 :
3737 :
3738 0 : class HCompareNumericAndBranch : public HTemplateControlInstruction<2, 2> {
3739 : public:
3740 : static HCompareNumericAndBranch* New(Isolate* isolate, Zone* zone,
3741 : HValue* context, HValue* left,
3742 : HValue* right, Token::Value token,
3743 : HBasicBlock* true_target = NULL,
3744 : HBasicBlock* false_target = NULL) {
3745 : return new (zone)
3746 190259 : HCompareNumericAndBranch(left, right, token, true_target, false_target);
3747 : }
3748 :
3749 2281150 : HValue* left() const { return OperandAt(0); }
3750 2255659 : HValue* right() const { return OperandAt(1); }
3751 : Token::Value token() const { return token_; }
3752 :
3753 : void set_observed_input_representation(Representation left,
3754 : Representation right) {
3755 80894 : observed_input_representation_[0] = left;
3756 80894 : observed_input_representation_[1] = right;
3757 : }
3758 :
3759 : void InferRepresentation(HInferRepresentationPhase* h_infer) override;
3760 :
3761 429902 : Representation RequiredInputRepresentation(int index) override {
3762 429902 : return representation();
3763 : }
3764 852888 : Representation observed_input_representation(int index) override {
3765 852888 : return observed_input_representation_[index];
3766 : }
3767 :
3768 : bool KnownSuccessorBlock(HBasicBlock** block) override;
3769 :
3770 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
3771 :
3772 5330966 : DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)
3773 :
3774 : private:
3775 190259 : HCompareNumericAndBranch(HValue* left, HValue* right, Token::Value token,
3776 : HBasicBlock* true_target, HBasicBlock* false_target)
3777 570777 : : token_(token) {
3778 : SetFlag(kFlexibleRepresentation);
3779 : DCHECK(Token::IsCompareOp(token));
3780 190259 : SetOperandAt(0, left);
3781 190259 : SetOperandAt(1, right);
3782 : SetSuccessorAt(0, true_target);
3783 : SetSuccessorAt(1, false_target);
3784 190259 : }
3785 :
3786 : Representation observed_input_representation_[2];
3787 : Token::Value token_;
3788 : };
3789 :
3790 :
3791 0 : class HCompareHoleAndBranch final : public HUnaryControlInstruction {
3792 : public:
3793 66 : DECLARE_INSTRUCTION_FACTORY_P1(HCompareHoleAndBranch, HValue*);
3794 : DECLARE_INSTRUCTION_FACTORY_P3(HCompareHoleAndBranch, HValue*,
3795 : HBasicBlock*, HBasicBlock*);
3796 :
3797 : void InferRepresentation(HInferRepresentationPhase* h_infer) override;
3798 :
3799 33 : Representation RequiredInputRepresentation(int index) override {
3800 33 : return representation();
3801 : }
3802 :
3803 942 : DECLARE_CONCRETE_INSTRUCTION(CompareHoleAndBranch)
3804 :
3805 : private:
3806 33 : HCompareHoleAndBranch(HValue* value,
3807 : HBasicBlock* true_target = NULL,
3808 : HBasicBlock* false_target = NULL)
3809 33 : : HUnaryControlInstruction(value, true_target, false_target) {
3810 : SetFlag(kFlexibleRepresentation);
3811 33 : }
3812 : };
3813 :
3814 :
3815 0 : class HCompareObjectEqAndBranch : public HTemplateControlInstruction<2, 2> {
3816 : public:
3817 86580 : DECLARE_INSTRUCTION_FACTORY_P2(HCompareObjectEqAndBranch, HValue*, HValue*);
3818 460 : DECLARE_INSTRUCTION_FACTORY_P4(HCompareObjectEqAndBranch, HValue*, HValue*,
3819 : HBasicBlock*, HBasicBlock*);
3820 :
3821 : bool KnownSuccessorBlock(HBasicBlock** block) override;
3822 :
3823 : static const int kNoKnownSuccessorIndex = -1;
3824 : int known_successor_index() const { return known_successor_index_; }
3825 : void set_known_successor_index(int known_successor_index) {
3826 0 : known_successor_index_ = known_successor_index;
3827 : }
3828 :
3829 130051 : HValue* left() const { return OperandAt(0); }
3830 88351 : HValue* right() const { return OperandAt(1); }
3831 :
3832 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
3833 :
3834 96159 : Representation RequiredInputRepresentation(int index) override {
3835 96159 : return Representation::Tagged();
3836 : }
3837 :
3838 17665 : Representation observed_input_representation(int index) override {
3839 17665 : return Representation::Tagged();
3840 : }
3841 :
3842 1136064 : DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)
3843 :
3844 : private:
3845 43750 : HCompareObjectEqAndBranch(HValue* left,
3846 : HValue* right,
3847 : HBasicBlock* true_target = NULL,
3848 : HBasicBlock* false_target = NULL)
3849 43750 : : known_successor_index_(kNoKnownSuccessorIndex) {
3850 43750 : SetOperandAt(0, left);
3851 43750 : SetOperandAt(1, right);
3852 : SetSuccessorAt(0, true_target);
3853 : SetSuccessorAt(1, false_target);
3854 43750 : }
3855 :
3856 : int known_successor_index_;
3857 : };
3858 :
3859 :
3860 0 : class HIsStringAndBranch final : public HUnaryControlInstruction {
3861 : public:
3862 902 : DECLARE_INSTRUCTION_FACTORY_P1(HIsStringAndBranch, HValue*);
3863 23 : DECLARE_INSTRUCTION_FACTORY_P3(HIsStringAndBranch, HValue*,
3864 : HBasicBlock*, HBasicBlock*);
3865 :
3866 499 : Representation RequiredInputRepresentation(int index) override {
3867 499 : return Representation::Tagged();
3868 : }
3869 :
3870 : bool KnownSuccessorBlock(HBasicBlock** block) override;
3871 :
3872 : static const int kNoKnownSuccessorIndex = -1;
3873 : int known_successor_index() const { return known_successor_index_; }
3874 : void set_known_successor_index(int known_successor_index) {
3875 6 : known_successor_index_ = known_successor_index;
3876 : }
3877 :
3878 13391 : DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
3879 :
3880 : protected:
3881 948 : int RedefinedOperandIndex() override { return 0; }
3882 :
3883 : private:
3884 474 : HIsStringAndBranch(HValue* value, HBasicBlock* true_target = NULL,
3885 : HBasicBlock* false_target = NULL)
3886 : : HUnaryControlInstruction(value, true_target, false_target),
3887 474 : known_successor_index_(kNoKnownSuccessorIndex) {
3888 : set_representation(Representation::Tagged());
3889 474 : }
3890 :
3891 : int known_successor_index_;
3892 : };
3893 :
3894 :
3895 0 : class HIsSmiAndBranch final : public HUnaryControlInstruction {
3896 : public:
3897 16990 : DECLARE_INSTRUCTION_FACTORY_P1(HIsSmiAndBranch, HValue*);
3898 705 : DECLARE_INSTRUCTION_FACTORY_P3(HIsSmiAndBranch, HValue*,
3899 : HBasicBlock*, HBasicBlock*);
3900 :
3901 273315 : DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)
3902 :
3903 10571 : Representation RequiredInputRepresentation(int index) override {
3904 10571 : return Representation::Tagged();
3905 : }
3906 :
3907 : protected:
3908 0 : bool DataEquals(HValue* other) override { return true; }
3909 18388 : int RedefinedOperandIndex() override { return 0; }
3910 :
3911 : private:
3912 9200 : HIsSmiAndBranch(HValue* value,
3913 : HBasicBlock* true_target = NULL,
3914 : HBasicBlock* false_target = NULL)
3915 9200 : : HUnaryControlInstruction(value, true_target, false_target) {
3916 : set_representation(Representation::Tagged());
3917 9200 : }
3918 : };
3919 :
3920 :
3921 0 : class HIsUndetectableAndBranch final : public HUnaryControlInstruction {
3922 : public:
3923 2976 : DECLARE_INSTRUCTION_FACTORY_P1(HIsUndetectableAndBranch, HValue*);
3924 : DECLARE_INSTRUCTION_FACTORY_P3(HIsUndetectableAndBranch, HValue*,
3925 : HBasicBlock*, HBasicBlock*);
3926 :
3927 1594 : Representation RequiredInputRepresentation(int index) override {
3928 1594 : return Representation::Tagged();
3929 : }
3930 :
3931 : bool KnownSuccessorBlock(HBasicBlock** block) override;
3932 :
3933 36909 : DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)
3934 :
3935 : private:
3936 : HIsUndetectableAndBranch(HValue* value,
3937 : HBasicBlock* true_target = NULL,
3938 : HBasicBlock* false_target = NULL)
3939 1488 : : HUnaryControlInstruction(value, true_target, false_target) {}
3940 : };
3941 :
3942 :
3943 0 : class HStringCompareAndBranch final : public HTemplateControlInstruction<2, 3> {
3944 : public:
3945 15294 : DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HStringCompareAndBranch,
3946 : HValue*,
3947 : HValue*,
3948 : Token::Value);
3949 :
3950 15235 : HValue* context() const { return OperandAt(0); }
3951 15235 : HValue* left() const { return OperandAt(1); }
3952 15235 : HValue* right() const { return OperandAt(2); }
3953 : Token::Value token() const { return token_; }
3954 :
3955 : std::ostream& PrintDataTo(std::ostream& os) const final; // NOLINT
3956 :
3957 45846 : Representation RequiredInputRepresentation(int index) final {
3958 45846 : return Representation::Tagged();
3959 : }
3960 :
3961 417959 : DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)
3962 :
3963 : private:
3964 15294 : HStringCompareAndBranch(HValue* context, HValue* left, HValue* right,
3965 : Token::Value token)
3966 15294 : : token_(token) {
3967 : DCHECK(Token::IsCompareOp(token));
3968 15294 : SetOperandAt(0, context);
3969 15294 : SetOperandAt(1, left);
3970 15294 : SetOperandAt(2, right);
3971 : set_representation(Representation::Tagged());
3972 : SetChangesFlag(kNewSpacePromotion);
3973 : SetDependsOnFlag(kStringChars);
3974 : SetDependsOnFlag(kStringLengths);
3975 15294 : }
3976 :
3977 : Token::Value const token_;
3978 : };
3979 :
3980 :
3981 0 : class HHasInstanceTypeAndBranch final : public HUnaryControlInstruction {
3982 : public:
3983 882 : DECLARE_INSTRUCTION_FACTORY_P2(
3984 : HHasInstanceTypeAndBranch, HValue*, InstanceType);
3985 1090 : DECLARE_INSTRUCTION_FACTORY_P3(
3986 : HHasInstanceTypeAndBranch, HValue*, InstanceType, InstanceType);
3987 :
3988 : InstanceType from() { return from_; }
3989 : InstanceType to() { return to_; }
3990 :
3991 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
3992 :
3993 2084 : Representation RequiredInputRepresentation(int index) override {
3994 2084 : return Representation::Tagged();
3995 : }
3996 :
3997 : bool KnownSuccessorBlock(HBasicBlock** block) override;
3998 :
3999 50912 : DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
4000 :
4001 : private:
4002 882 : HHasInstanceTypeAndBranch(HValue* value, InstanceType type)
4003 882 : : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { }
4004 1090 : HHasInstanceTypeAndBranch(HValue* value, InstanceType from, InstanceType to)
4005 1090 : : HUnaryControlInstruction(value, NULL, NULL), from_(from), to_(to) {
4006 : DCHECK(to == LAST_TYPE); // Others not implemented yet in backend.
4007 1090 : }
4008 :
4009 : InstanceType from_;
4010 : InstanceType to_; // Inclusive range, not all combinations work.
4011 : };
4012 :
4013 0 : class HClassOfTestAndBranch final : public HUnaryControlInstruction {
4014 : public:
4015 15394 : DECLARE_INSTRUCTION_FACTORY_P2(HClassOfTestAndBranch, HValue*,
4016 : Handle<String>);
4017 :
4018 189512 : DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)
4019 :
4020 7790 : Representation RequiredInputRepresentation(int index) override {
4021 7790 : return Representation::Tagged();
4022 : }
4023 :
4024 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
4025 :
4026 : Handle<String> class_name() const { return class_name_; }
4027 :
4028 : private:
4029 7697 : HClassOfTestAndBranch(HValue* value, Handle<String> class_name)
4030 7697 : : HUnaryControlInstruction(value, NULL, NULL), class_name_(class_name) {}
4031 :
4032 : Handle<String> class_name_;
4033 : };
4034 :
4035 0 : class HTypeofIsAndBranch final : public HUnaryControlInstruction {
4036 : public:
4037 132730 : DECLARE_INSTRUCTION_FACTORY_P2(HTypeofIsAndBranch, HValue*, Handle<String>);
4038 :
4039 : Handle<String> type_literal() const { return type_literal_.handle(); }
4040 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
4041 :
4042 1446272 : DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
4043 :
4044 70403 : Representation RequiredInputRepresentation(int index) override {
4045 70403 : return Representation::None();
4046 : }
4047 :
4048 : bool KnownSuccessorBlock(HBasicBlock** block) override;
4049 :
4050 66201 : void FinalizeUniqueness() override {
4051 66201 : type_literal_ = Unique<String>(type_literal_.handle());
4052 66201 : }
4053 :
4054 : private:
4055 66365 : HTypeofIsAndBranch(HValue* value, Handle<String> type_literal)
4056 : : HUnaryControlInstruction(value, NULL, NULL),
4057 66365 : type_literal_(Unique<String>::CreateUninitialized(type_literal)) { }
4058 :
4059 : Unique<String> type_literal_;
4060 : };
4061 :
4062 :
4063 0 : class HHasInPrototypeChainAndBranch final
4064 : : public HTemplateControlInstruction<2, 2> {
4065 : public:
4066 323 : DECLARE_INSTRUCTION_FACTORY_P2(HHasInPrototypeChainAndBranch, HValue*,
4067 : HValue*);
4068 :
4069 932 : HValue* object() const { return OperandAt(0); }
4070 319 : HValue* prototype() const { return OperandAt(1); }
4071 :
4072 643 : Representation RequiredInputRepresentation(int index) override {
4073 643 : return Representation::Tagged();
4074 : }
4075 :
4076 319 : bool ObjectNeedsSmiCheck() const {
4077 613 : return !object()->type().IsHeapObject() &&
4078 319 : !object()->representation().IsHeapObject();
4079 : }
4080 :
4081 8022 : DECLARE_CONCRETE_INSTRUCTION(HasInPrototypeChainAndBranch)
4082 :
4083 : private:
4084 323 : HHasInPrototypeChainAndBranch(HValue* object, HValue* prototype) {
4085 323 : SetOperandAt(0, object);
4086 323 : SetOperandAt(1, prototype);
4087 : SetDependsOnFlag(kCalls);
4088 323 : }
4089 : };
4090 :
4091 :
4092 0 : class HPower final : public HTemplateInstruction<2> {
4093 : public:
4094 : static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4095 : HValue* left, HValue* right);
4096 :
4097 : HValue* left() { return OperandAt(0); }
4098 : HValue* right() const { return OperandAt(1); }
4099 :
4100 2466 : Representation RequiredInputRepresentation(int index) override {
4101 : return index == 0
4102 : ? Representation::Double()
4103 2510 : : Representation::None();
4104 : }
4105 44 : Representation observed_input_representation(int index) override {
4106 44 : return RequiredInputRepresentation(index);
4107 : }
4108 :
4109 185765 : DECLARE_CONCRETE_INSTRUCTION(Power)
4110 :
4111 : protected:
4112 119 : bool DataEquals(HValue* other) override { return true; }
4113 :
4114 : private:
4115 1942 : HPower(HValue* left, HValue* right) {
4116 971 : SetOperandAt(0, left);
4117 971 : SetOperandAt(1, right);
4118 : set_representation(Representation::Double());
4119 : SetFlag(kUseGVN);
4120 : SetChangesFlag(kNewSpacePromotion);
4121 971 : }
4122 :
4123 0 : bool IsDeletable() const override {
4124 0 : return !right()->representation().IsTagged();
4125 : }
4126 : };
4127 :
4128 :
4129 : enum ExternalAddType {
4130 : AddOfExternalAndTagged,
4131 : AddOfExternalAndInt32,
4132 : NoExternalAdd
4133 : };
4134 :
4135 :
4136 0 : class HAdd final : public HArithmeticBinaryOperation {
4137 : public:
4138 : static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4139 : HValue* left, HValue* right);
4140 : static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4141 : HValue* left, HValue* right,
4142 : ExternalAddType external_add_type);
4143 :
4144 : // Add is only commutative if two integer values are added and not if two
4145 : // tagged values are added (because it might be a String concatenation).
4146 : // We also do not commute (pointer + offset).
4147 555504 : bool IsCommutative() const override {
4148 555504 : return !representation().IsTagged() && !representation().IsExternal();
4149 : }
4150 :
4151 : HValue* Canonicalize() override;
4152 :
4153 324071 : void RepresentationChanged(Representation to) override {
4154 663588 : if (to.IsTagged() &&
4155 5094 : (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved() ||
4156 458 : left()->ToStringCanBeObserved() || right()->ToStringCanBeObserved())) {
4157 : SetAllSideEffects();
4158 : ClearFlag(kUseGVN);
4159 : } else {
4160 : ClearAllSideEffects();
4161 : SetFlag(kUseGVN);
4162 : }
4163 324071 : if (to.IsTagged()) {
4164 : SetChangesFlag(kNewSpacePromotion);
4165 : ClearFlag(kTruncatingToNumber);
4166 : }
4167 445638 : if (!right()->type().IsTaggedNumber() &&
4168 445198 : !right()->representation().IsDouble() &&
4169 : !right()->representation().IsSmiOrInteger32()) {
4170 : ClearFlag(kTruncatingToNumber);
4171 : }
4172 324071 : }
4173 :
4174 : Representation RepresentationFromInputs() override;
4175 :
4176 : Representation RequiredInputRepresentation(int index) override;
4177 :
4178 : bool IsConsistentExternalRepresentation() {
4179 : return left()->representation().IsExternal() &&
4180 : ((external_add_type_ == AddOfExternalAndInt32 &&
4181 : right()->representation().IsInteger32()) ||
4182 : (external_add_type_ == AddOfExternalAndTagged &&
4183 : right()->representation().IsTagged()));
4184 : }
4185 :
4186 : ExternalAddType external_add_type() const { return external_add_type_; }
4187 :
4188 9262775 : DECLARE_CONCRETE_INSTRUCTION(Add)
4189 :
4190 : protected:
4191 28888 : bool DataEquals(HValue* other) override { return true; }
4192 :
4193 : Range* InferRange(Zone* zone) override;
4194 :
4195 : private:
4196 292654 : HAdd(HValue* context, HValue* left, HValue* right,
4197 : ExternalAddType external_add_type = NoExternalAdd)
4198 : : HArithmeticBinaryOperation(context, left, right, HType::Tagged()),
4199 292654 : external_add_type_(external_add_type) {
4200 : SetFlag(kCanOverflow);
4201 292654 : switch (external_add_type_) {
4202 : case AddOfExternalAndTagged:
4203 : DCHECK(left->representation().IsExternal());
4204 : DCHECK(right->representation().IsTagged());
4205 : SetDependsOnFlag(kNewSpacePromotion);
4206 : ClearFlag(HValue::kCanOverflow);
4207 : SetFlag(kHasNoObservableSideEffects);
4208 : break;
4209 :
4210 : case NoExternalAdd:
4211 : // This is a bit of a hack: The call to this constructor is generated
4212 : // by a macro that also supports sub and mul, so it doesn't pass in
4213 : // a value for external_add_type but uses the default.
4214 288757 : if (left->representation().IsExternal()) {
4215 0 : external_add_type_ = AddOfExternalAndInt32;
4216 : }
4217 : break;
4218 :
4219 : case AddOfExternalAndInt32:
4220 : // See comment above.
4221 0 : UNREACHABLE();
4222 : break;
4223 : }
4224 292654 : }
4225 :
4226 : ExternalAddType external_add_type_;
4227 : };
4228 :
4229 :
4230 0 : class HSub final : public HArithmeticBinaryOperation {
4231 : public:
4232 : static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4233 : HValue* left, HValue* right);
4234 :
4235 : HValue* Canonicalize() override;
4236 :
4237 1012103 : DECLARE_CONCRETE_INSTRUCTION(Sub)
4238 :
4239 : protected:
4240 2010 : bool DataEquals(HValue* other) override { return true; }
4241 :
4242 : Range* InferRange(Zone* zone) override;
4243 :
4244 : private:
4245 : HSub(HValue* context, HValue* left, HValue* right)
4246 26374 : : HArithmeticBinaryOperation(context, left, right) {
4247 : SetFlag(kCanOverflow);
4248 : }
4249 : };
4250 :
4251 :
4252 0 : class HMul final : public HArithmeticBinaryOperation {
4253 : public:
4254 : static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4255 : HValue* left, HValue* right);
4256 :
4257 607 : static HInstruction* NewImul(Isolate* isolate, Zone* zone, HValue* context,
4258 : HValue* left, HValue* right) {
4259 607 : HInstruction* instr = HMul::New(isolate, zone, context, left, right);
4260 1214 : if (!instr->IsMul()) return instr;
4261 : HMul* mul = HMul::cast(instr);
4262 : // TODO(mstarzinger): Prevent bailout on minus zero for imul.
4263 607 : mul->AssumeRepresentation(Representation::Integer32());
4264 : mul->ClearFlag(HValue::kCanOverflow);
4265 607 : return mul;
4266 : }
4267 :
4268 : HValue* Canonicalize() override;
4269 :
4270 : // Only commutative if it is certain that not two objects are multiplicated.
4271 41604 : bool IsCommutative() const override { return !representation().IsTagged(); }
4272 :
4273 74563 : void UpdateRepresentation(Representation new_rep,
4274 : HInferRepresentationPhase* h_infer,
4275 : const char* reason) override {
4276 74563 : HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4277 74563 : }
4278 :
4279 : bool MulMinusOne();
4280 :
4281 985963 : DECLARE_CONCRETE_INSTRUCTION(Mul)
4282 :
4283 : protected:
4284 3881 : bool DataEquals(HValue* other) override { return true; }
4285 :
4286 : Range* InferRange(Zone* zone) override;
4287 :
4288 : private:
4289 : HMul(HValue* context, HValue* left, HValue* right)
4290 27279 : : HArithmeticBinaryOperation(context, left, right) {
4291 : SetFlag(kCanOverflow);
4292 : }
4293 : };
4294 :
4295 :
4296 0 : class HMod final : public HArithmeticBinaryOperation {
4297 : public:
4298 : static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4299 : HValue* left, HValue* right);
4300 :
4301 : HValue* Canonicalize() override;
4302 :
4303 20530 : void UpdateRepresentation(Representation new_rep,
4304 : HInferRepresentationPhase* h_infer,
4305 : const char* reason) override {
4306 20530 : if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4307 20530 : HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4308 20530 : }
4309 :
4310 406551 : DECLARE_CONCRETE_INSTRUCTION(Mod)
4311 :
4312 : protected:
4313 227 : bool DataEquals(HValue* other) override { return true; }
4314 :
4315 : Range* InferRange(Zone* zone) override;
4316 :
4317 : private:
4318 5635 : HMod(HValue* context, HValue* left, HValue* right)
4319 5635 : : HArithmeticBinaryOperation(context, left, right) {
4320 : SetFlag(kCanBeDivByZero);
4321 : SetFlag(kCanOverflow);
4322 : SetFlag(kLeftCanBeNegative);
4323 5635 : }
4324 : };
4325 :
4326 :
4327 0 : class HDiv final : public HArithmeticBinaryOperation {
4328 : public:
4329 : static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4330 : HValue* left, HValue* right);
4331 :
4332 : HValue* Canonicalize() override;
4333 :
4334 120326 : void UpdateRepresentation(Representation new_rep,
4335 : HInferRepresentationPhase* h_infer,
4336 : const char* reason) override {
4337 120326 : if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4338 120326 : HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4339 120326 : }
4340 :
4341 1560305 : DECLARE_CONCRETE_INSTRUCTION(Div)
4342 :
4343 : protected:
4344 1189 : bool DataEquals(HValue* other) override { return true; }
4345 :
4346 : Range* InferRange(Zone* zone) override;
4347 :
4348 : private:
4349 52355 : HDiv(HValue* context, HValue* left, HValue* right)
4350 52355 : : HArithmeticBinaryOperation(context, left, right) {
4351 : SetFlag(kCanBeDivByZero);
4352 : SetFlag(kCanOverflow);
4353 52355 : }
4354 : };
4355 :
4356 :
4357 0 : class HMathMinMax final : public HArithmeticBinaryOperation {
4358 : public:
4359 : enum Operation { kMathMin, kMathMax };
4360 :
4361 : static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4362 : HValue* left, HValue* right, Operation op);
4363 :
4364 459 : Representation observed_input_representation(int index) override {
4365 459 : return RequiredInputRepresentation(index);
4366 : }
4367 :
4368 : void InferRepresentation(HInferRepresentationPhase* h_infer) override;
4369 :
4370 2203 : Representation RepresentationFromInputs() override {
4371 2203 : Representation left_rep = left()->representation();
4372 2203 : Representation right_rep = right()->representation();
4373 2203 : Representation result = Representation::Smi();
4374 2203 : result = result.generalize(left_rep);
4375 2203 : result = result.generalize(right_rep);
4376 2203 : if (result.IsTagged()) return Representation::Double();
4377 1263 : return result;
4378 : }
4379 :
4380 426 : bool IsCommutative() const override { return true; }
4381 :
4382 : Operation operation() { return operation_; }
4383 :
4384 125497 : DECLARE_CONCRETE_INSTRUCTION(MathMinMax)
4385 :
4386 : protected:
4387 181 : bool DataEquals(HValue* other) override {
4388 362 : return other->IsMathMinMax() &&
4389 362 : HMathMinMax::cast(other)->operation_ == operation_;
4390 : }
4391 :
4392 : Range* InferRange(Zone* zone) override;
4393 :
4394 : private:
4395 : HMathMinMax(HValue* context, HValue* left, HValue* right, Operation op)
4396 1715 : : HArithmeticBinaryOperation(context, left, right), operation_(op) {}
4397 :
4398 : Operation operation_;
4399 : };
4400 :
4401 :
4402 0 : class HBitwise final : public HBitwiseBinaryOperation {
4403 : public:
4404 : static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4405 : Token::Value op, HValue* left, HValue* right);
4406 :
4407 : Token::Value op() const { return op_; }
4408 :
4409 179728 : bool IsCommutative() const override { return true; }
4410 :
4411 : HValue* Canonicalize() override;
4412 :
4413 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
4414 :
4415 3110727 : DECLARE_CONCRETE_INSTRUCTION(Bitwise)
4416 :
4417 : protected:
4418 15881 : bool DataEquals(HValue* other) override {
4419 15881 : return op() == HBitwise::cast(other)->op();
4420 : }
4421 :
4422 : Range* InferRange(Zone* zone) override;
4423 :
4424 : private:
4425 139726 : HBitwise(HValue* context, Token::Value op, HValue* left, HValue* right)
4426 139726 : : HBitwiseBinaryOperation(context, left, right), op_(op) {
4427 : DCHECK(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR);
4428 : // BIT_AND with a smi-range positive value will always unset the
4429 : // entire sign-extension of the smi-sign.
4430 360021 : if (op == Token::BIT_AND &&
4431 2754 : ((left->IsConstant() &&
4432 0 : left->representation().IsSmi() &&
4433 80569 : HConstant::cast(left)->Integer32Value() >= 0) ||
4434 64705 : (right->IsConstant() &&
4435 0 : right->representation().IsSmi() &&
4436 0 : HConstant::cast(right)->Integer32Value() >= 0))) {
4437 : SetFlag(kTruncatingToSmi);
4438 : SetFlag(kTruncatingToInt32);
4439 : // BIT_OR with a smi-range negative value will always set the entire
4440 : // sign-extension of the smi-sign.
4441 310103 : } else if (op == Token::BIT_OR &&
4442 643 : ((left->IsConstant() &&
4443 0 : left->representation().IsSmi() &&
4444 30651 : HConstant::cast(left)->Integer32Value() < 0) ||
4445 23005 : (right->IsConstant() &&
4446 0 : right->representation().IsSmi() &&
4447 0 : HConstant::cast(right)->Integer32Value() < 0))) {
4448 : SetFlag(kTruncatingToSmi);
4449 : SetFlag(kTruncatingToInt32);
4450 : }
4451 139726 : }
4452 :
4453 : Token::Value op_;
4454 : };
4455 :
4456 :
4457 0 : class HShl final : public HBitwiseBinaryOperation {
4458 : public:
4459 : static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4460 : HValue* left, HValue* right);
4461 :
4462 : Range* InferRange(Zone* zone) override;
4463 :
4464 64956 : void UpdateRepresentation(Representation new_rep,
4465 : HInferRepresentationPhase* h_infer,
4466 : const char* reason) override {
4467 130474 : if (new_rep.IsSmi() &&
4468 : !(right()->IsInteger32Constant() &&
4469 0 : right()->GetInteger32Constant() >= 0)) {
4470 : new_rep = Representation::Integer32();
4471 : }
4472 : HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4473 64956 : }
4474 :
4475 531329 : DECLARE_CONCRETE_INSTRUCTION(Shl)
4476 :
4477 : protected:
4478 96 : bool DataEquals(HValue* other) override { return true; }
4479 :
4480 : private:
4481 : HShl(HValue* context, HValue* left, HValue* right)
4482 16562 : : HBitwiseBinaryOperation(context, left, right) {}
4483 : };
4484 :
4485 :
4486 0 : class HShr final : public HBitwiseBinaryOperation {
4487 : public:
4488 : static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4489 : HValue* left, HValue* right);
4490 :
4491 : Range* InferRange(Zone* zone) override;
4492 :
4493 34654 : void UpdateRepresentation(Representation new_rep,
4494 : HInferRepresentationPhase* h_infer,
4495 : const char* reason) override {
4496 34654 : if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4497 : HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4498 34654 : }
4499 :
4500 578760 : DECLARE_CONCRETE_INSTRUCTION(Shr)
4501 :
4502 : protected:
4503 171 : bool DataEquals(HValue* other) override { return true; }
4504 :
4505 : private:
4506 : HShr(HValue* context, HValue* left, HValue* right)
4507 9359 : : HBitwiseBinaryOperation(context, left, right) {}
4508 : };
4509 :
4510 :
4511 0 : class HSar final : public HBitwiseBinaryOperation {
4512 : public:
4513 : static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4514 : HValue* left, HValue* right);
4515 :
4516 : Range* InferRange(Zone* zone) override;
4517 :
4518 45134 : void UpdateRepresentation(Representation new_rep,
4519 : HInferRepresentationPhase* h_infer,
4520 : const char* reason) override {
4521 45134 : if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4522 : HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4523 45134 : }
4524 :
4525 520305 : DECLARE_CONCRETE_INSTRUCTION(Sar)
4526 :
4527 : protected:
4528 842 : bool DataEquals(HValue* other) override { return true; }
4529 :
4530 : private:
4531 : HSar(HValue* context, HValue* left, HValue* right)
4532 14637 : : HBitwiseBinaryOperation(context, left, right) {}
4533 : };
4534 :
4535 :
4536 0 : class HRor final : public HBitwiseBinaryOperation {
4537 : public:
4538 : static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
4539 : HValue* left, HValue* right) {
4540 500 : return new (zone) HRor(context, left, right);
4541 : }
4542 :
4543 2700 : void UpdateRepresentation(Representation new_rep,
4544 : HInferRepresentationPhase* h_infer,
4545 : const char* reason) override {
4546 2700 : if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4547 : HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4548 2700 : }
4549 :
4550 16089 : DECLARE_CONCRETE_INSTRUCTION(Ror)
4551 :
4552 : protected:
4553 0 : bool DataEquals(HValue* other) override { return true; }
4554 :
4555 : private:
4556 500 : HRor(HValue* context, HValue* left, HValue* right)
4557 500 : : HBitwiseBinaryOperation(context, left, right) {
4558 500 : ChangeRepresentation(Representation::Integer32());
4559 500 : }
4560 : };
4561 :
4562 :
4563 0 : class HOsrEntry final : public HTemplateInstruction<0> {
4564 : public:
4565 4876 : DECLARE_INSTRUCTION_FACTORY_P1(HOsrEntry, BailoutId);
4566 :
4567 : BailoutId ast_id() const { return ast_id_; }
4568 :
4569 0 : Representation RequiredInputRepresentation(int index) override {
4570 0 : return Representation::None();
4571 : }
4572 :
4573 26852 : DECLARE_CONCRETE_INSTRUCTION(OsrEntry)
4574 :
4575 : private:
4576 2438 : explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
4577 : SetChangesFlag(kOsrEntries);
4578 : SetChangesFlag(kNewSpacePromotion);
4579 : }
4580 :
4581 : BailoutId ast_id_;
4582 : };
4583 :
4584 :
4585 0 : class HParameter final : public HTemplateInstruction<0> {
4586 : public:
4587 : enum ParameterKind {
4588 : STACK_PARAMETER,
4589 : REGISTER_PARAMETER
4590 : };
4591 :
4592 855582 : DECLARE_INSTRUCTION_FACTORY_P1(HParameter, unsigned);
4593 : DECLARE_INSTRUCTION_FACTORY_P2(HParameter, unsigned, ParameterKind);
4594 74354 : DECLARE_INSTRUCTION_FACTORY_P3(HParameter, unsigned, ParameterKind,
4595 : Representation);
4596 :
4597 : unsigned index() const { return index_; }
4598 : ParameterKind kind() const { return kind_; }
4599 :
4600 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
4601 :
4602 0 : Representation RequiredInputRepresentation(int index) override {
4603 0 : return Representation::None();
4604 : }
4605 :
4606 9630 : Representation KnownOptimalRepresentation() override {
4607 : // If a parameter is an input to a phi, that phi should not
4608 : // choose any more optimistic representation than Tagged.
4609 9630 : return Representation::Tagged();
4610 : }
4611 :
4612 50160204 : DECLARE_CONCRETE_INSTRUCTION(Parameter)
4613 :
4614 : private:
4615 : explicit HParameter(unsigned index,
4616 : ParameterKind kind = STACK_PARAMETER)
4617 : : index_(index),
4618 427791 : kind_(kind) {
4619 : set_representation(Representation::Tagged());
4620 : }
4621 :
4622 : explicit HParameter(unsigned index,
4623 : ParameterKind kind,
4624 : Representation r)
4625 : : index_(index),
4626 37177 : kind_(kind) {
4627 : set_representation(r);
4628 : }
4629 :
4630 : unsigned index_;
4631 : ParameterKind kind_;
4632 : };
4633 :
4634 :
4635 0 : class HUnknownOSRValue final : public HTemplateInstruction<0> {
4636 : public:
4637 29078 : DECLARE_INSTRUCTION_FACTORY_P2(HUnknownOSRValue, HEnvironment*, int);
4638 :
4639 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
4640 :
4641 0 : Representation RequiredInputRepresentation(int index) override {
4642 0 : return Representation::None();
4643 : }
4644 :
4645 3835 : void set_incoming_value(HPhi* value) { incoming_value_ = value; }
4646 : HPhi* incoming_value() { return incoming_value_; }
4647 : HEnvironment *environment() { return environment_; }
4648 : int index() { return index_; }
4649 :
4650 13826 : Representation KnownOptimalRepresentation() override {
4651 13826 : if (incoming_value_ == NULL) return Representation::None();
4652 : return incoming_value_->KnownOptimalRepresentation();
4653 : }
4654 :
4655 429726 : DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
4656 :
4657 : private:
4658 : HUnknownOSRValue(HEnvironment* environment, int index)
4659 : : environment_(environment),
4660 : index_(index),
4661 14539 : incoming_value_(NULL) {
4662 : set_representation(Representation::Tagged());
4663 : }
4664 :
4665 : HEnvironment* environment_;
4666 : int index_;
4667 : HPhi* incoming_value_;
4668 : };
4669 :
4670 0 : class HAllocate final : public HTemplateInstruction<3> {
4671 : public:
4672 : static bool CompatibleInstanceTypes(InstanceType type1,
4673 : InstanceType type2) {
4674 : return ComputeFlags(TENURED, type1) == ComputeFlags(TENURED, type2) &&
4675 : ComputeFlags(NOT_TENURED, type1) == ComputeFlags(NOT_TENURED, type2);
4676 : }
4677 :
4678 36045 : static HAllocate* New(
4679 : Isolate* isolate, Zone* zone, HValue* context, HValue* size, HType type,
4680 : PretenureFlag pretenure_flag, InstanceType instance_type,
4681 : HValue* dominator,
4682 : Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null()) {
4683 : return new (zone) HAllocate(context, size, type, pretenure_flag,
4684 72090 : instance_type, dominator, allocation_site);
4685 : }
4686 :
4687 : // Maximum instance size for which allocations will be inlined.
4688 : static const int kMaxInlineSize = 64 * kPointerSize;
4689 :
4690 : HValue* context() const { return OperandAt(0); }
4691 : HValue* size() const { return OperandAt(1); }
4692 : HValue* allocation_folding_dominator() const { return OperandAt(2); }
4693 :
4694 72526 : Representation RequiredInputRepresentation(int index) override {
4695 72526 : if (index == 0) {
4696 : return Representation::Tagged();
4697 : } else {
4698 : return Representation::Integer32();
4699 : }
4700 : }
4701 :
4702 8884 : Handle<Map> GetMonomorphicJSObjectMap() override {
4703 8884 : return known_initial_map_;
4704 : }
4705 :
4706 : void set_known_initial_map(Handle<Map> known_initial_map) {
4707 4599 : known_initial_map_ = known_initial_map;
4708 : }
4709 :
4710 : bool IsNewSpaceAllocation() const {
4711 118839 : return (flags_ & ALLOCATE_IN_NEW_SPACE) != 0;
4712 : }
4713 :
4714 : bool IsOldSpaceAllocation() const {
4715 47986 : return (flags_ & ALLOCATE_IN_OLD_SPACE) != 0;
4716 : }
4717 :
4718 : bool MustAllocateDoubleAligned() const {
4719 31414 : return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0;
4720 : }
4721 :
4722 : bool MustPrefillWithFiller() const {
4723 20528 : return (flags_ & PREFILL_WITH_FILLER) != 0;
4724 : }
4725 :
4726 : void MakePrefillWithFiller() {
4727 : flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER);
4728 : }
4729 :
4730 : void MakeDoubleAligned() {
4731 378 : flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED);
4732 : }
4733 :
4734 : void MakeAllocationFoldingDominator() {
4735 : flags_ =
4736 2074 : static_cast<HAllocate::Flags>(flags_ | ALLOCATION_FOLDING_DOMINATOR);
4737 : }
4738 :
4739 : bool IsAllocationFoldingDominator() const {
4740 69694 : return (flags_ & ALLOCATION_FOLDING_DOMINATOR) != 0;
4741 : }
4742 :
4743 4903 : void MakeFoldedAllocation(HAllocate* dominator) {
4744 4903 : flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATION_FOLDED);
4745 : ClearFlag(kTrackSideEffectDominators);
4746 : ClearChangesFlag(kNewSpacePromotion);
4747 4903 : SetOperandAt(2, dominator);
4748 4903 : }
4749 :
4750 145353 : bool IsAllocationFolded() const { return (flags_ & ALLOCATION_FOLDED) != 0; }
4751 :
4752 : bool HandleSideEffectDominator(GVNFlag side_effect,
4753 : HValue* dominator) override;
4754 :
4755 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
4756 :
4757 2462721 : DECLARE_CONCRETE_INSTRUCTION(Allocate)
4758 :
4759 : private:
4760 : enum Flags {
4761 : ALLOCATE_IN_NEW_SPACE = 1 << 0,
4762 : ALLOCATE_IN_OLD_SPACE = 1 << 2,
4763 : ALLOCATE_DOUBLE_ALIGNED = 1 << 3,
4764 : PREFILL_WITH_FILLER = 1 << 4,
4765 : ALLOCATION_FOLDING_DOMINATOR = 1 << 5,
4766 : ALLOCATION_FOLDED = 1 << 6
4767 : };
4768 :
4769 36045 : HAllocate(
4770 : HValue* context, HValue* size, HType type, PretenureFlag pretenure_flag,
4771 : InstanceType instance_type, HValue* dominator,
4772 : Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null())
4773 : : HTemplateInstruction<3>(type),
4774 72090 : flags_(ComputeFlags(pretenure_flag, instance_type)) {
4775 36045 : SetOperandAt(0, context);
4776 : UpdateSize(size);
4777 36045 : SetOperandAt(2, dominator);
4778 : set_representation(Representation::Tagged());
4779 : SetFlag(kTrackSideEffectDominators);
4780 : SetChangesFlag(kNewSpacePromotion);
4781 : SetDependsOnFlag(kNewSpacePromotion);
4782 :
4783 36045 : if (FLAG_trace_pretenuring) {
4784 : PrintF("HAllocate with AllocationSite %p %s\n",
4785 : allocation_site.is_null()
4786 : ? static_cast<void*>(NULL)
4787 : : static_cast<void*>(*allocation_site),
4788 0 : pretenure_flag == TENURED ? "tenured" : "not tenured");
4789 : }
4790 36045 : }
4791 :
4792 : static Flags ComputeFlags(PretenureFlag pretenure_flag,
4793 : InstanceType instance_type) {
4794 : Flags flags = pretenure_flag == TENURED ? ALLOCATE_IN_OLD_SPACE
4795 36045 : : ALLOCATE_IN_NEW_SPACE;
4796 36045 : if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
4797 505 : flags = static_cast<Flags>(flags | ALLOCATE_DOUBLE_ALIGNED);
4798 : }
4799 : // We have to fill the allocated object with one word fillers if we do
4800 : // not use allocation folding since some allocations may depend on each
4801 : // other, i.e., have a pointer to each other. A GC in between these
4802 : // allocations may leave such objects behind in a not completely initialized
4803 : // state.
4804 36045 : if (!FLAG_use_gvn || !FLAG_use_allocation_folding) {
4805 129 : flags = static_cast<Flags>(flags | PREFILL_WITH_FILLER);
4806 : }
4807 : return flags;
4808 : }
4809 :
4810 : void UpdateSize(HValue* size) {
4811 38874 : SetOperandAt(1, size);
4812 : }
4813 :
4814 2829 : bool IsFoldable(HAllocate* allocate) {
4815 5658 : return (IsNewSpaceAllocation() && allocate->IsNewSpaceAllocation()) ||
4816 37 : (IsOldSpaceAllocation() && allocate->IsOldSpaceAllocation());
4817 : }
4818 :
4819 : Flags flags_;
4820 : Handle<Map> known_initial_map_;
4821 : };
4822 :
4823 :
4824 0 : class HStoreCodeEntry final : public HTemplateInstruction<2> {
4825 : public:
4826 : static HStoreCodeEntry* New(Isolate* isolate, Zone* zone, HValue* context,
4827 : HValue* function, HValue* code) {
4828 : return new(zone) HStoreCodeEntry(function, code);
4829 : }
4830 :
4831 0 : Representation RequiredInputRepresentation(int index) override {
4832 0 : return Representation::Tagged();
4833 : }
4834 :
4835 : HValue* function() { return OperandAt(0); }
4836 : HValue* code_object() { return OperandAt(1); }
4837 :
4838 0 : DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry)
4839 :
4840 : private:
4841 : HStoreCodeEntry(HValue* function, HValue* code) {
4842 : SetOperandAt(0, function);
4843 : SetOperandAt(1, code);
4844 : }
4845 : };
4846 :
4847 :
4848 0 : class HInnerAllocatedObject final : public HTemplateInstruction<2> {
4849 : public:
4850 7160 : static HInnerAllocatedObject* New(Isolate* isolate, Zone* zone,
4851 : HValue* context, HValue* value,
4852 : HValue* offset, HType type) {
4853 14320 : return new(zone) HInnerAllocatedObject(value, offset, type);
4854 : }
4855 :
4856 : HValue* base_object() const { return OperandAt(0); }
4857 : HValue* offset() const { return OperandAt(1); }
4858 :
4859 14320 : Representation RequiredInputRepresentation(int index) override {
4860 14320 : return index == 0 ? Representation::Tagged() : Representation::Integer32();
4861 : }
4862 :
4863 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
4864 :
4865 211147 : DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject)
4866 :
4867 : private:
4868 7160 : HInnerAllocatedObject(HValue* value,
4869 : HValue* offset,
4870 7160 : HType type) : HTemplateInstruction<2>(type) {
4871 : DCHECK(value->IsAllocate());
4872 : DCHECK(type.IsHeapObject());
4873 7160 : SetOperandAt(0, value);
4874 7160 : SetOperandAt(1, offset);
4875 : set_representation(Representation::Tagged());
4876 7160 : }
4877 : };
4878 :
4879 :
4880 416959 : inline bool StoringValueNeedsWriteBarrier(HValue* value) {
4881 : return !value->type().IsSmi()
4882 354378 : && !value->type().IsNull()
4883 351001 : && !value->type().IsBoolean()
4884 348255 : && !value->type().IsUndefined()
4885 738085 : && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable());
4886 : }
4887 :
4888 :
4889 178516 : inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
4890 : HValue* value,
4891 : HValue* dominator) {
4892 : // There may be multiple inner allocates dominated by one allocate.
4893 385672 : while (object->IsInnerAllocatedObject()) {
4894 : object = HInnerAllocatedObject::cast(object)->base_object();
4895 : }
4896 :
4897 178516 : if (object->IsAllocate()) {
4898 119605 : HAllocate* allocate = HAllocate::cast(object);
4899 119605 : if (allocate->IsAllocationFolded()) {
4900 : HValue* dominator = allocate->allocation_folding_dominator();
4901 : // There is no guarantee that all allocations are folded together because
4902 : // GVN performs a fixpoint.
4903 45950 : if (HAllocate::cast(dominator)->IsAllocationFoldingDominator()) {
4904 : object = dominator;
4905 : }
4906 : }
4907 : }
4908 :
4909 186794 : if (object->IsConstant() &&
4910 8278 : HConstant::cast(object)->HasExternalReferenceValue()) {
4911 : // Stores to external references require no write barriers
4912 : return false;
4913 : }
4914 : // We definitely need a write barrier unless the object is the allocation
4915 : // dominator.
4916 289859 : if (object == dominator && object->IsAllocate()) {
4917 : // Stores to new space allocations require no write barriers.
4918 220970 : if (HAllocate::cast(object)->IsNewSpaceAllocation()) {
4919 : return false;
4920 : }
4921 : }
4922 68167 : return true;
4923 : }
4924 :
4925 :
4926 21332 : inline PointersToHereCheck PointersToHereCheckForObject(HValue* object,
4927 : HValue* dominator) {
4928 42664 : while (object->IsInnerAllocatedObject()) {
4929 : object = HInnerAllocatedObject::cast(object)->base_object();
4930 : }
4931 28556 : if (object == dominator &&
4932 21991 : object->IsAllocate() &&
4933 659 : HAllocate::cast(object)->IsNewSpaceAllocation()) {
4934 : return kPointersToHereAreAlwaysInteresting;
4935 : }
4936 20674 : return kPointersToHereMaybeInteresting;
4937 : }
4938 :
4939 :
4940 0 : class HLoadContextSlot final : public HUnaryOperation {
4941 : public:
4942 : enum Mode {
4943 : // Perform a normal load of the context slot without checking its value.
4944 : kNoCheck,
4945 : // Load and check the value of the context slot. Deoptimize if it's the
4946 : // hole value. This is used for checking for loading of uninitialized
4947 : // harmony bindings where we deoptimize into full-codegen generated code
4948 : // which will subsequently throw a reference error.
4949 : kCheckDeoptimize
4950 : };
4951 :
4952 389339 : HLoadContextSlot(HValue* context, int slot_index, Mode mode)
4953 389339 : : HUnaryOperation(context), slot_index_(slot_index), mode_(mode) {
4954 : set_representation(Representation::Tagged());
4955 : SetFlag(kUseGVN);
4956 : SetDependsOnFlag(kContextSlots);
4957 389339 : }
4958 :
4959 : int slot_index() const { return slot_index_; }
4960 : Mode mode() const { return mode_; }
4961 :
4962 : bool DeoptimizesOnHole() {
4963 : return mode_ == kCheckDeoptimize;
4964 : }
4965 :
4966 : bool RequiresHoleCheck() const {
4967 : return mode_ != kNoCheck;
4968 : }
4969 :
4970 387812 : Representation RequiredInputRepresentation(int index) override {
4971 387812 : return Representation::Tagged();
4972 : }
4973 :
4974 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
4975 :
4976 13334291 : DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)
4977 :
4978 : protected:
4979 92572 : bool DataEquals(HValue* other) override {
4980 92572 : HLoadContextSlot* b = HLoadContextSlot::cast(other);
4981 92572 : return (slot_index() == b->slot_index());
4982 : }
4983 :
4984 : private:
4985 172 : bool IsDeletable() const override { return !RequiresHoleCheck(); }
4986 :
4987 : int slot_index_;
4988 : Mode mode_;
4989 : };
4990 :
4991 :
4992 0 : class HStoreContextSlot final : public HTemplateInstruction<2> {
4993 : public:
4994 : enum Mode {
4995 : // Perform a normal store to the context slot without checking its previous
4996 : // value.
4997 : kNoCheck,
4998 : // Check the previous value of the context slot and deoptimize if it's the
4999 : // hole value. This is used for checking for assignments to uninitialized
5000 : // harmony bindings where we deoptimize into full-codegen generated code
5001 : // which will subsequently throw a reference error.
5002 : kCheckDeoptimize
5003 : };
5004 :
5005 70842 : DECLARE_INSTRUCTION_FACTORY_P4(HStoreContextSlot, HValue*, int,
5006 : Mode, HValue*);
5007 :
5008 : HValue* context() const { return OperandAt(0); }
5009 : HValue* value() const { return OperandAt(1); }
5010 : int slot_index() const { return slot_index_; }
5011 : Mode mode() const { return mode_; }
5012 :
5013 : bool NeedsWriteBarrier() {
5014 140055 : return StoringValueNeedsWriteBarrier(value());
5015 : }
5016 :
5017 : bool DeoptimizesOnHole() {
5018 : return mode_ == kCheckDeoptimize;
5019 : }
5020 :
5021 : bool RequiresHoleCheck() {
5022 : return mode_ != kNoCheck;
5023 : }
5024 :
5025 142467 : Representation RequiredInputRepresentation(int index) override {
5026 142467 : return Representation::Tagged();
5027 : }
5028 :
5029 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
5030 :
5031 912171 : DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
5032 :
5033 : private:
5034 70842 : HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
5035 70842 : : slot_index_(slot_index), mode_(mode) {
5036 70842 : SetOperandAt(0, context);
5037 70842 : SetOperandAt(1, value);
5038 : SetChangesFlag(kContextSlots);
5039 70842 : }
5040 :
5041 : int slot_index_;
5042 : Mode mode_;
5043 : };
5044 :
5045 :
5046 : // Represents an access to a portion of an object, such as the map pointer,
5047 : // array elements pointer, etc, but not accesses to array elements themselves.
5048 : class HObjectAccess final {
5049 : public:
5050 : inline bool IsInobject() const {
5051 1282739 : return portion() != kBackingStore && portion() != kExternalMemory;
5052 : }
5053 :
5054 : inline bool IsExternalMemory() const {
5055 : return portion() == kExternalMemory;
5056 : }
5057 :
5058 : inline bool IsStringLength() const {
5059 : return portion() == kStringLengths;
5060 : }
5061 :
5062 : inline bool IsMap() const {
5063 : return portion() == kMaps;
5064 : }
5065 :
5066 : inline int offset() const {
5067 : return OffsetField::decode(value_);
5068 : }
5069 :
5070 : inline Representation representation() const {
5071 : return Representation::FromKind(RepresentationField::decode(value_));
5072 : }
5073 :
5074 : inline Handle<Name> name() const { return name_; }
5075 :
5076 : inline bool immutable() const {
5077 : return ImmutableField::decode(value_);
5078 : }
5079 :
5080 : // Returns true if access is being made to an in-object property that
5081 : // was already added to the object.
5082 : inline bool existing_inobject_property() const {
5083 : return ExistingInobjectPropertyField::decode(value_);
5084 : }
5085 :
5086 19359 : inline HObjectAccess WithRepresentation(Representation representation) {
5087 : return HObjectAccess(portion(), offset(), representation, name(),
5088 19359 : immutable(), existing_inobject_property());
5089 : }
5090 :
5091 : static HObjectAccess ForHeapNumberValue() {
5092 : return HObjectAccess(
5093 : kDouble, HeapNumber::kValueOffset, Representation::Double());
5094 : }
5095 :
5096 : static HObjectAccess ForHeapNumberValueLowestBits() {
5097 : return HObjectAccess(kDouble,
5098 : HeapNumber::kValueOffset,
5099 : Representation::Integer32());
5100 : }
5101 :
5102 : static HObjectAccess ForHeapNumberValueHighestBits() {
5103 : return HObjectAccess(kDouble,
5104 : HeapNumber::kValueOffset + kIntSize,
5105 : Representation::Integer32());
5106 : }
5107 :
5108 : static HObjectAccess ForOddballToNumber(
5109 : Representation representation = Representation::Tagged()) {
5110 : return HObjectAccess(kInobject, Oddball::kToNumberOffset, representation);
5111 : }
5112 :
5113 : static HObjectAccess ForOddballTypeOf() {
5114 : return HObjectAccess(kInobject, Oddball::kTypeOfOffset,
5115 : Representation::HeapObject());
5116 : }
5117 :
5118 : static HObjectAccess ForElementsPointer() {
5119 : return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
5120 : }
5121 :
5122 : static HObjectAccess ForNextFunctionLinkPointer() {
5123 : return HObjectAccess(kInobject, JSFunction::kNextFunctionLinkOffset);
5124 : }
5125 :
5126 : static HObjectAccess ForArrayLength(ElementsKind elements_kind) {
5127 : return HObjectAccess(
5128 : kArrayLengths,
5129 : JSArray::kLengthOffset,
5130 : IsFastElementsKind(elements_kind)
5131 57298 : ? Representation::Smi() : Representation::Tagged());
5132 : }
5133 :
5134 : static HObjectAccess ForAllocationSiteOffset(int offset);
5135 :
5136 : static HObjectAccess ForAllocationSiteList() {
5137 : return HObjectAccess(kExternalMemory, 0, Representation::Tagged(),
5138 : Handle<Name>::null(), false, false);
5139 : }
5140 :
5141 : static HObjectAccess ForFixedArrayLength() {
5142 : return HObjectAccess(
5143 : kArrayLengths,
5144 : FixedArray::kLengthOffset,
5145 : Representation::Smi());
5146 : }
5147 :
5148 : static HObjectAccess ForFixedTypedArrayBaseBasePointer() {
5149 : return HObjectAccess(kInobject, FixedTypedArrayBase::kBasePointerOffset,
5150 : Representation::Tagged());
5151 : }
5152 :
5153 3897 : static HObjectAccess ForFixedTypedArrayBaseExternalPointer() {
5154 : return HObjectAccess::ForObservableJSObjectOffset(
5155 : FixedTypedArrayBase::kExternalPointerOffset,
5156 3897 : Representation::External());
5157 : }
5158 :
5159 : static HObjectAccess ForStringHashField() {
5160 : return HObjectAccess(kInobject,
5161 : String::kHashFieldOffset,
5162 : Representation::Integer32());
5163 : }
5164 :
5165 : static HObjectAccess ForStringLength() {
5166 : STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
5167 : return HObjectAccess(
5168 : kStringLengths,
5169 : String::kLengthOffset,
5170 : Representation::Smi());
5171 : }
5172 :
5173 : static HObjectAccess ForConsStringFirst() {
5174 : return HObjectAccess(kInobject, ConsString::kFirstOffset);
5175 : }
5176 :
5177 : static HObjectAccess ForConsStringSecond() {
5178 : return HObjectAccess(kInobject, ConsString::kSecondOffset);
5179 : }
5180 :
5181 : static HObjectAccess ForPropertiesPointer() {
5182 : return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
5183 : }
5184 :
5185 : static HObjectAccess ForPrototypeOrInitialMap() {
5186 : return HObjectAccess(kInobject, JSFunction::kPrototypeOrInitialMapOffset);
5187 : }
5188 :
5189 : static HObjectAccess ForSharedFunctionInfoPointer() {
5190 : return HObjectAccess(kInobject, JSFunction::kSharedFunctionInfoOffset);
5191 : }
5192 :
5193 : static HObjectAccess ForCodeEntryPointer() {
5194 : return HObjectAccess(kInobject, JSFunction::kCodeEntryOffset);
5195 : }
5196 :
5197 : static HObjectAccess ForCodeOffset() {
5198 : return HObjectAccess(kInobject, SharedFunctionInfo::kCodeOffset);
5199 : }
5200 :
5201 : static HObjectAccess ForOptimizedCodeMap() {
5202 : return HObjectAccess(kInobject,
5203 : SharedFunctionInfo::kOptimizedCodeMapOffset);
5204 : }
5205 :
5206 : static HObjectAccess ForFunctionContextPointer() {
5207 : return HObjectAccess(kInobject, JSFunction::kContextOffset);
5208 : }
5209 :
5210 : static HObjectAccess ForMap() {
5211 : return HObjectAccess(kMaps, JSObject::kMapOffset);
5212 : }
5213 :
5214 : static HObjectAccess ForPrototype() {
5215 : return HObjectAccess(kMaps, Map::kPrototypeOffset);
5216 : }
5217 :
5218 : static HObjectAccess ForMapAsInteger32() {
5219 : return HObjectAccess(kMaps, JSObject::kMapOffset,
5220 : Representation::Integer32());
5221 : }
5222 :
5223 : static HObjectAccess ForMapInObjectPropertiesOrConstructorFunctionIndex() {
5224 : return HObjectAccess(
5225 : kInobject, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset,
5226 : Representation::UInteger8());
5227 : }
5228 :
5229 : static HObjectAccess ForMapInstanceType() {
5230 : return HObjectAccess(kInobject,
5231 : Map::kInstanceTypeOffset,
5232 : Representation::UInteger8());
5233 : }
5234 :
5235 : static HObjectAccess ForMapInstanceSize() {
5236 : return HObjectAccess(kInobject,
5237 : Map::kInstanceSizeOffset,
5238 : Representation::UInteger8());
5239 : }
5240 :
5241 : static HObjectAccess ForMapBitField() {
5242 : return HObjectAccess(kInobject,
5243 : Map::kBitFieldOffset,
5244 : Representation::UInteger8());
5245 : }
5246 :
5247 : static HObjectAccess ForMapBitField2() {
5248 : return HObjectAccess(kInobject,
5249 : Map::kBitField2Offset,
5250 : Representation::UInteger8());
5251 : }
5252 :
5253 : static HObjectAccess ForMapBitField3() {
5254 : return HObjectAccess(kInobject, Map::kBitField3Offset,
5255 : Representation::Integer32());
5256 : }
5257 :
5258 : static HObjectAccess ForMapDescriptors() {
5259 : return HObjectAccess(kInobject, Map::kDescriptorsOffset);
5260 : }
5261 :
5262 : static HObjectAccess ForNameHashField() {
5263 : return HObjectAccess(kInobject,
5264 : Name::kHashFieldOffset,
5265 : Representation::Integer32());
5266 : }
5267 :
5268 : static HObjectAccess ForMapInstanceTypeAndBitField() {
5269 : STATIC_ASSERT((Map::kInstanceTypeAndBitFieldOffset & 1) == 0);
5270 : // Ensure the two fields share one 16-bit word, endian-independent.
5271 : STATIC_ASSERT((Map::kBitFieldOffset & ~1) ==
5272 : (Map::kInstanceTypeOffset & ~1));
5273 : return HObjectAccess(kInobject,
5274 : Map::kInstanceTypeAndBitFieldOffset,
5275 : Representation::UInteger16());
5276 : }
5277 :
5278 : static HObjectAccess ForPropertyCellValue() {
5279 : return HObjectAccess(kInobject, PropertyCell::kValueOffset);
5280 : }
5281 :
5282 : static HObjectAccess ForPropertyCellDetails() {
5283 : return HObjectAccess(kInobject, PropertyCell::kDetailsOffset,
5284 : Representation::Smi());
5285 : }
5286 :
5287 : static HObjectAccess ForCellValue() {
5288 : return HObjectAccess(kInobject, Cell::kValueOffset);
5289 : }
5290 :
5291 : static HObjectAccess ForWeakCellValue() {
5292 : return HObjectAccess(kInobject, WeakCell::kValueOffset);
5293 : }
5294 :
5295 : static HObjectAccess ForWeakCellNext() {
5296 : return HObjectAccess(kInobject, WeakCell::kNextOffset);
5297 : }
5298 :
5299 : static HObjectAccess ForAllocationMementoSite() {
5300 : return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset);
5301 : }
5302 :
5303 : static HObjectAccess ForCounter() {
5304 : return HObjectAccess(kExternalMemory, 0, Representation::Integer32(),
5305 : Handle<Name>::null(), false, false);
5306 : }
5307 :
5308 : static HObjectAccess ForExternalUInteger8() {
5309 : return HObjectAccess(kExternalMemory, 0, Representation::UInteger8(),
5310 : Handle<Name>::null(), false, false);
5311 : }
5312 :
5313 : static HObjectAccess ForBoundTargetFunction() {
5314 : return HObjectAccess(kInobject,
5315 : JSBoundFunction::kBoundTargetFunctionOffset);
5316 : }
5317 :
5318 : static HObjectAccess ForBoundThis() {
5319 : return HObjectAccess(kInobject, JSBoundFunction::kBoundThisOffset);
5320 : }
5321 :
5322 : static HObjectAccess ForBoundArguments() {
5323 : return HObjectAccess(kInobject, JSBoundFunction::kBoundArgumentsOffset);
5324 : }
5325 :
5326 : // Create an access to an offset in a fixed array header.
5327 : static HObjectAccess ForFixedArrayHeader(int offset);
5328 :
5329 : // Create an access to an in-object property in a JSObject.
5330 : // This kind of access must be used when the object |map| is known and
5331 : // in-object properties are being accessed. Accesses of the in-object
5332 : // properties can have different semantics depending on whether corresponding
5333 : // property was added to the map or not.
5334 : static HObjectAccess ForMapAndOffset(Handle<Map> map, int offset,
5335 : Representation representation = Representation::Tagged());
5336 :
5337 : // Create an access to an in-object property in a JSObject.
5338 : // This kind of access can be used for accessing object header fields or
5339 : // in-object properties if the map of the object is not known.
5340 : static HObjectAccess ForObservableJSObjectOffset(int offset,
5341 : Representation representation = Representation::Tagged()) {
5342 6364 : return ForMapAndOffset(Handle<Map>::null(), offset, representation);
5343 : }
5344 :
5345 : // Create an access to an in-object property in a JSArray.
5346 : static HObjectAccess ForJSArrayOffset(int offset);
5347 :
5348 : static HObjectAccess ForContextSlot(int index);
5349 :
5350 : static HObjectAccess ForScriptContext(int index);
5351 :
5352 : // Create an access to the backing store of an object.
5353 : static HObjectAccess ForBackingStoreOffset(int offset,
5354 : Representation representation = Representation::Tagged());
5355 :
5356 : // Create an access to a resolved field (in-object or backing store).
5357 : static HObjectAccess ForField(Handle<Map> map, int index,
5358 : Representation representation,
5359 : Handle<Name> name);
5360 :
5361 : static HObjectAccess ForJSTypedArrayLength() {
5362 : return HObjectAccess::ForObservableJSObjectOffset(
5363 : JSTypedArray::kLengthOffset);
5364 : }
5365 :
5366 : static HObjectAccess ForJSArrayBufferBackingStore() {
5367 : return HObjectAccess::ForObservableJSObjectOffset(
5368 : JSArrayBuffer::kBackingStoreOffset, Representation::External());
5369 : }
5370 :
5371 0 : static HObjectAccess ForJSArrayBufferByteLength() {
5372 : return HObjectAccess::ForObservableJSObjectOffset(
5373 0 : JSArrayBuffer::kByteLengthOffset, Representation::Tagged());
5374 : }
5375 :
5376 189 : static HObjectAccess ForJSArrayBufferBitField() {
5377 : return HObjectAccess::ForObservableJSObjectOffset(
5378 189 : JSArrayBuffer::kBitFieldOffset, Representation::Integer32());
5379 : }
5380 :
5381 : static HObjectAccess ForJSArrayBufferBitFieldSlot() {
5382 : return HObjectAccess::ForObservableJSObjectOffset(
5383 : JSArrayBuffer::kBitFieldSlot, Representation::Smi());
5384 : }
5385 :
5386 189 : static HObjectAccess ForJSArrayBufferViewBuffer() {
5387 : return HObjectAccess::ForObservableJSObjectOffset(
5388 189 : JSArrayBufferView::kBufferOffset);
5389 : }
5390 :
5391 : static HObjectAccess ForJSArrayBufferViewByteOffset() {
5392 : return HObjectAccess::ForObservableJSObjectOffset(
5393 : JSArrayBufferView::kByteOffsetOffset);
5394 : }
5395 :
5396 : static HObjectAccess ForJSArrayBufferViewByteLength() {
5397 : return HObjectAccess::ForObservableJSObjectOffset(
5398 : JSArrayBufferView::kByteLengthOffset);
5399 : }
5400 :
5401 : static HObjectAccess ForJSGlobalObjectNativeContext() {
5402 : return HObjectAccess(kInobject, JSGlobalObject::kNativeContextOffset);
5403 : }
5404 :
5405 : static HObjectAccess ForJSRegExpFlags() {
5406 : return HObjectAccess(kInobject, JSRegExp::kFlagsOffset);
5407 : }
5408 :
5409 : static HObjectAccess ForJSRegExpSource() {
5410 : return HObjectAccess(kInobject, JSRegExp::kSourceOffset);
5411 : }
5412 :
5413 1553 : static HObjectAccess ForJSCollectionTable() {
5414 : return HObjectAccess::ForObservableJSObjectOffset(
5415 1553 : JSCollection::kTableOffset);
5416 : }
5417 :
5418 : template <typename CollectionType>
5419 : static HObjectAccess ForOrderedHashTableNumberOfBuckets() {
5420 : return HObjectAccess(kInobject, CollectionType::kNumberOfBucketsOffset,
5421 : Representation::Smi());
5422 : }
5423 :
5424 : template <typename CollectionType>
5425 : static HObjectAccess ForOrderedHashTableNumberOfElements() {
5426 : return HObjectAccess(kInobject, CollectionType::kNumberOfElementsOffset,
5427 : Representation::Smi());
5428 : }
5429 :
5430 : template <typename CollectionType>
5431 : static HObjectAccess ForOrderedHashTableNumberOfDeletedElements() {
5432 : return HObjectAccess(kInobject,
5433 : CollectionType::kNumberOfDeletedElementsOffset,
5434 : Representation::Smi());
5435 : }
5436 :
5437 : template <typename CollectionType>
5438 : static HObjectAccess ForOrderedHashTableNextTable() {
5439 : return HObjectAccess(kInobject, CollectionType::kNextTableOffset);
5440 : }
5441 :
5442 : template <typename CollectionType>
5443 : static HObjectAccess ForOrderedHashTableBucket(int bucket) {
5444 : return HObjectAccess(kInobject, CollectionType::kHashTableStartOffset +
5445 : (bucket * kPointerSize),
5446 6 : Representation::Smi());
5447 : }
5448 :
5449 : // Access into the data table of an OrderedHashTable with a
5450 : // known-at-compile-time bucket count.
5451 : template <typename CollectionType, int kBucketCount>
5452 : static HObjectAccess ForOrderedHashTableDataTableIndex(int index) {
5453 : return HObjectAccess(kInobject, CollectionType::kHashTableStartOffset +
5454 : (kBucketCount * kPointerSize) +
5455 28 : (index * kPointerSize));
5456 : }
5457 :
5458 : inline bool Equals(HObjectAccess that) const {
5459 : return value_ == that.value_; // portion and offset must match
5460 : }
5461 :
5462 : protected:
5463 : void SetGVNFlags(HValue *instr, PropertyAccessType access_type);
5464 :
5465 : private:
5466 : // internal use only; different parts of an object or array
5467 : enum Portion {
5468 : kMaps, // map of an object
5469 : kArrayLengths, // the length of an array
5470 : kStringLengths, // the length of a string
5471 : kElementsPointer, // elements pointer
5472 : kBackingStore, // some field in the backing store
5473 : kDouble, // some double field
5474 : kInobject, // some other in-object field
5475 : kExternalMemory // some field in external memory
5476 : };
5477 :
5478 11913090 : HObjectAccess() : value_(0) {}
5479 :
5480 : HObjectAccess(Portion portion, int offset,
5481 : Representation representation = Representation::Tagged(),
5482 : Handle<Name> name = Handle<Name>::null(),
5483 : bool immutable = false, bool existing_inobject_property = true)
5484 189551 : : value_(PortionField::encode(portion) |
5485 19359 : RepresentationField::encode(representation.kind()) |
5486 183446 : ImmutableField::encode(immutable ? 1 : 0) |
5487 : ExistingInobjectPropertyField::encode(
5488 293743 : existing_inobject_property ? 1 : 0) |
5489 : OffsetField::encode(offset)),
5490 : name_(name) {
5491 : // assert that the fields decode correctly
5492 : DCHECK(this->offset() == offset);
5493 : DCHECK(this->portion() == portion);
5494 : DCHECK(this->immutable() == immutable);
5495 : DCHECK(this->existing_inobject_property() == existing_inobject_property);
5496 : DCHECK(RepresentationField::decode(value_) == representation.kind());
5497 : DCHECK(!this->existing_inobject_property() || IsInobject());
5498 : }
5499 :
5500 : class PortionField : public BitField<Portion, 0, 3> {};
5501 : class RepresentationField : public BitField<Representation::Kind, 3, 4> {};
5502 : class ImmutableField : public BitField<bool, 7, 1> {};
5503 : class ExistingInobjectPropertyField : public BitField<bool, 8, 1> {};
5504 : class OffsetField : public BitField<int, 9, 23> {};
5505 :
5506 : uint32_t value_; // encodes portion, representation, immutable, and offset
5507 : Handle<Name> name_;
5508 :
5509 : friend class HLoadNamedField;
5510 : friend class HStoreNamedField;
5511 : friend class SideEffectsTracker;
5512 : friend std::ostream& operator<<(std::ostream& os,
5513 : const HObjectAccess& access);
5514 :
5515 : inline Portion portion() const {
5516 : return PortionField::decode(value_);
5517 : }
5518 : };
5519 :
5520 :
5521 : std::ostream& operator<<(std::ostream& os, const HObjectAccess& access);
5522 :
5523 :
5524 0 : class HLoadNamedField final : public HTemplateInstruction<2> {
5525 : public:
5526 614238 : DECLARE_INSTRUCTION_FACTORY_P3(HLoadNamedField, HValue*,
5527 : HValue*, HObjectAccess);
5528 21266 : DECLARE_INSTRUCTION_FACTORY_P5(HLoadNamedField, HValue*, HValue*,
5529 : HObjectAccess, const UniqueSet<Map>*, HType);
5530 :
5531 : HValue* object() const { return OperandAt(0); }
5532 : HValue* dependency() const {
5533 : DCHECK(HasDependency());
5534 : return OperandAt(1);
5535 : }
5536 : bool HasDependency() const { return OperandAt(0) != OperandAt(1); }
5537 : HObjectAccess access() const { return access_; }
5538 : Representation field_representation() const {
5539 : return access_.representation();
5540 : }
5541 :
5542 : const UniqueSet<Map>* maps() const { return maps_; }
5543 :
5544 4118 : bool HasEscapingOperandAt(int index) override { return false; }
5545 4118 : bool HasOutOfBoundsAccess(int size) override {
5546 8236 : return !access().IsInobject() || access().offset() >= size;
5547 : }
5548 599472 : Representation RequiredInputRepresentation(int index) override {
5549 599472 : if (index == 0) {
5550 : // object must be external in case of external memory access
5551 : return access().IsExternalMemory() ? Representation::External()
5552 301749 : : Representation::Tagged();
5553 : }
5554 : DCHECK(index == 1);
5555 : return Representation::None();
5556 : }
5557 : Range* InferRange(Zone* zone) override;
5558 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
5559 :
5560 30206 : bool CanBeReplacedWith(HValue* other) const {
5561 60412 : if (!CheckFlag(HValue::kCantBeReplaced)) return false;
5562 0 : if (!type().Equals(other->type())) return false;
5563 0 : if (!representation().Equals(other->representation())) return false;
5564 0 : if (!other->IsLoadNamedField()) return true;
5565 : HLoadNamedField* that = HLoadNamedField::cast(other);
5566 0 : if (this->maps_ == that->maps_) return true;
5567 0 : if (this->maps_ == NULL || that->maps_ == NULL) return false;
5568 0 : return this->maps_->IsSubset(that->maps_);
5569 : }
5570 :
5571 13481291 : DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
5572 :
5573 : protected:
5574 42816 : bool DataEquals(HValue* other) override {
5575 : HLoadNamedField* that = HLoadNamedField::cast(other);
5576 42816 : if (!this->access_.Equals(that->access_)) return false;
5577 35770 : if (this->maps_ == that->maps_) return true;
5578 307 : return (this->maps_ != NULL &&
5579 614 : that->maps_ != NULL &&
5580 307 : this->maps_->Equals(that->maps_));
5581 : }
5582 :
5583 : private:
5584 307119 : HLoadNamedField(HValue* object,
5585 : HValue* dependency,
5586 : HObjectAccess access)
5587 307119 : : access_(access), maps_(NULL) {
5588 : DCHECK_NOT_NULL(object);
5589 307119 : SetOperandAt(0, object);
5590 307119 : SetOperandAt(1, dependency ? dependency : object);
5591 :
5592 307119 : Representation representation = access.representation();
5593 614238 : if (representation.IsInteger8() ||
5594 279209 : representation.IsUInteger8() ||
5595 586328 : representation.IsInteger16() ||
5596 : representation.IsUInteger16()) {
5597 : set_representation(Representation::Integer32());
5598 279209 : } else if (representation.IsSmi()) {
5599 : set_type(HType::Smi());
5600 : if (SmiValuesAre32Bits()) {
5601 : set_representation(Representation::Integer32());
5602 : } else {
5603 : set_representation(representation);
5604 : }
5605 320101 : } else if (representation.IsDouble() ||
5606 316204 : representation.IsExternal() ||
5607 : representation.IsInteger32()) {
5608 : set_representation(representation);
5609 152205 : } else if (representation.IsHeapObject()) {
5610 : set_type(HType::HeapObject());
5611 : set_representation(Representation::Tagged());
5612 : } else {
5613 : set_representation(Representation::Tagged());
5614 : }
5615 307119 : access.SetGVNFlags(this, LOAD);
5616 307119 : }
5617 :
5618 10633 : HLoadNamedField(HValue* object,
5619 : HValue* dependency,
5620 : HObjectAccess access,
5621 : const UniqueSet<Map>* maps,
5622 : HType type)
5623 10633 : : HTemplateInstruction<2>(type), access_(access), maps_(maps) {
5624 : DCHECK_NOT_NULL(maps);
5625 : DCHECK_NE(0, maps->size());
5626 :
5627 : DCHECK_NOT_NULL(object);
5628 10633 : SetOperandAt(0, object);
5629 10633 : SetOperandAt(1, dependency ? dependency : object);
5630 :
5631 : DCHECK(access.representation().IsHeapObject());
5632 : DCHECK(type.IsHeapObject());
5633 : set_representation(Representation::Tagged());
5634 :
5635 10633 : access.SetGVNFlags(this, LOAD);
5636 10633 : }
5637 :
5638 91 : bool IsDeletable() const override { return true; }
5639 :
5640 : HObjectAccess access_;
5641 : const UniqueSet<Map>* maps_;
5642 : };
5643 :
5644 :
5645 0 : class HLoadFunctionPrototype final : public HUnaryOperation {
5646 : public:
5647 6085 : DECLARE_INSTRUCTION_FACTORY_P1(HLoadFunctionPrototype, HValue*);
5648 :
5649 : HValue* function() { return OperandAt(0); }
5650 :
5651 6051 : Representation RequiredInputRepresentation(int index) override {
5652 6051 : return Representation::Tagged();
5653 : }
5654 :
5655 150740 : DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
5656 :
5657 : protected:
5658 8 : bool DataEquals(HValue* other) override { return true; }
5659 :
5660 : private:
5661 6085 : explicit HLoadFunctionPrototype(HValue* function)
5662 6085 : : HUnaryOperation(function) {
5663 : set_representation(Representation::Tagged());
5664 : SetFlag(kUseGVN);
5665 : SetDependsOnFlag(kCalls);
5666 6085 : }
5667 : };
5668 :
5669 80309 : class ArrayInstructionInterface {
5670 : public:
5671 : virtual HValue* GetKey() = 0;
5672 : virtual void SetKey(HValue* key) = 0;
5673 : virtual ElementsKind elements_kind() const = 0;
5674 : // TryIncreaseBaseOffset returns false if overflow would result.
5675 : virtual bool TryIncreaseBaseOffset(uint32_t increase_by_value) = 0;
5676 : virtual bool IsDehoisted() const = 0;
5677 : virtual void SetDehoisted(bool is_dehoisted) = 0;
5678 0 : virtual ~ArrayInstructionInterface() { }
5679 :
5680 : static Representation KeyedAccessIndexRequirement(Representation r) {
5681 : return r.IsInteger32() || SmiValuesAre32Bits()
5682 : ? Representation::Integer32() : Representation::Smi();
5683 : }
5684 : };
5685 :
5686 :
5687 : static const int kDefaultKeyedHeaderOffsetSentinel = -1;
5688 :
5689 : enum LoadKeyedHoleMode {
5690 : NEVER_RETURN_HOLE,
5691 : ALLOW_RETURN_HOLE,
5692 : CONVERT_HOLE_TO_UNDEFINED
5693 : };
5694 :
5695 :
5696 0 : class HLoadKeyed final : public HTemplateInstruction<4>,
5697 : public ArrayInstructionInterface {
5698 : public:
5699 4076 : DECLARE_INSTRUCTION_FACTORY_P5(HLoadKeyed, HValue*, HValue*, HValue*, HValue*,
5700 : ElementsKind);
5701 100026 : DECLARE_INSTRUCTION_FACTORY_P6(HLoadKeyed, HValue*, HValue*, HValue*, HValue*,
5702 : ElementsKind, LoadKeyedHoleMode);
5703 : DECLARE_INSTRUCTION_FACTORY_P7(HLoadKeyed, HValue*, HValue*, HValue*, HValue*,
5704 : ElementsKind, LoadKeyedHoleMode, int);
5705 :
5706 : bool is_fixed_typed_array() const {
5707 : return IsFixedTypedArrayElementsKind(elements_kind());
5708 : }
5709 : HValue* elements() const { return OperandAt(0); }
5710 : HValue* key() const { return OperandAt(1); }
5711 : HValue* dependency() const {
5712 : DCHECK(HasDependency());
5713 : return OperandAt(2);
5714 : }
5715 : bool HasDependency() const { return OperandAt(0) != OperandAt(2); }
5716 : HValue* backing_store_owner() const {
5717 : DCHECK(HasBackingStoreOwner());
5718 : return OperandAt(3);
5719 : }
5720 : bool HasBackingStoreOwner() const { return OperandAt(0) != OperandAt(3); }
5721 : uint32_t base_offset() const { return BaseOffsetField::decode(bit_field_); }
5722 : bool TryIncreaseBaseOffset(uint32_t increase_by_value) override;
5723 103240 : HValue* GetKey() override { return key(); }
5724 8050 : void SetKey(HValue* key) override { SetOperandAt(1, key); }
5725 0 : bool IsDehoisted() const override {
5726 50531 : return IsDehoistedField::decode(bit_field_);
5727 : }
5728 8050 : void SetDehoisted(bool is_dehoisted) override {
5729 16100 : bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
5730 8050 : }
5731 9246 : ElementsKind elements_kind() const override {
5732 263701 : return ElementsKindField::decode(bit_field_);
5733 : }
5734 : LoadKeyedHoleMode hole_mode() const {
5735 : return HoleModeField::decode(bit_field_);
5736 : }
5737 :
5738 299252 : Representation RequiredInputRepresentation(int index) override {
5739 : // kind_fast: tagged[int32] (none)
5740 : // kind_double: tagged[int32] (none)
5741 : // kind_fixed_typed_array: external[int32] (none)
5742 : // kind_external: external[int32] (none)
5743 243601 : if (index == 0) {
5744 : return is_fixed_typed_array() ? Representation::External()
5745 55651 : : Representation::Tagged();
5746 : }
5747 187950 : if (index == 1) {
5748 : return ArrayInstructionInterface::KeyedAccessIndexRequirement(
5749 : OperandAt(1)->representation());
5750 : }
5751 108966 : if (index == 2) {
5752 : return Representation::None();
5753 : }
5754 : DCHECK_EQ(3, index);
5755 : return HasBackingStoreOwner() ? Representation::Tagged()
5756 53701 : : Representation::None();
5757 : }
5758 :
5759 32892 : Representation observed_input_representation(int index) override {
5760 32892 : return RequiredInputRepresentation(index);
5761 : }
5762 :
5763 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
5764 :
5765 : bool UsesMustHandleHole() const;
5766 : bool AllUsesCanTreatHoleAsNaN() const;
5767 : bool RequiresHoleCheck() const;
5768 :
5769 : Range* InferRange(Zone* zone) override;
5770 :
5771 3786641 : DECLARE_CONCRETE_INSTRUCTION(LoadKeyed)
5772 :
5773 : protected:
5774 462 : bool DataEquals(HValue* other) override {
5775 231 : if (!other->IsLoadKeyed()) return false;
5776 231 : HLoadKeyed* other_load = HLoadKeyed::cast(other);
5777 :
5778 231 : if (base_offset() != other_load->base_offset()) return false;
5779 231 : return elements_kind() == other_load->elements_kind();
5780 : }
5781 :
5782 : private:
5783 52051 : HLoadKeyed(HValue* obj, HValue* key, HValue* dependency,
5784 : HValue* backing_store_owner, ElementsKind elements_kind,
5785 : LoadKeyedHoleMode mode = NEVER_RETURN_HOLE,
5786 52051 : int offset = kDefaultKeyedHeaderOffsetSentinel)
5787 52051 : : bit_field_(0) {
5788 : offset = offset == kDefaultKeyedHeaderOffsetSentinel
5789 : ? GetDefaultHeaderSizeForElementsKind(elements_kind)
5790 52051 : : offset;
5791 52051 : bit_field_ = ElementsKindField::encode(elements_kind) |
5792 52051 : HoleModeField::encode(mode) |
5793 104102 : BaseOffsetField::encode(offset);
5794 :
5795 52051 : SetOperandAt(0, obj);
5796 52051 : SetOperandAt(1, key);
5797 52051 : SetOperandAt(2, dependency != nullptr ? dependency : obj);
5798 52051 : SetOperandAt(3, backing_store_owner != nullptr ? backing_store_owner : obj);
5799 : DCHECK_EQ(HasBackingStoreOwner(), is_fixed_typed_array());
5800 :
5801 52051 : if (!is_fixed_typed_array()) {
5802 : // I can detect the case between storing double (holey and fast) and
5803 : // smi/object by looking at elements_kind_.
5804 : DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
5805 : IsFastDoubleElementsKind(elements_kind));
5806 :
5807 49949 : if (IsFastSmiOrObjectElementsKind(elements_kind)) {
5808 96155 : if (IsFastSmiElementsKind(elements_kind) &&
5809 578 : (!IsHoleyElementsKind(elements_kind) ||
5810 : mode == NEVER_RETURN_HOLE)) {
5811 : set_type(HType::Smi());
5812 7800 : if (SmiValuesAre32Bits() && !RequiresHoleCheck()) {
5813 : set_representation(Representation::Integer32());
5814 : } else {
5815 : set_representation(Representation::Smi());
5816 : }
5817 : } else {
5818 : set_representation(Representation::Tagged());
5819 : }
5820 :
5821 : SetDependsOnFlag(kArrayElements);
5822 : } else {
5823 : set_representation(Representation::Double());
5824 : SetDependsOnFlag(kDoubleArrayElements);
5825 : }
5826 : } else {
5827 2102 : if (elements_kind == FLOAT32_ELEMENTS ||
5828 : elements_kind == FLOAT64_ELEMENTS) {
5829 : set_representation(Representation::Double());
5830 : } else {
5831 : set_representation(Representation::Integer32());
5832 : }
5833 :
5834 2102 : if (is_fixed_typed_array()) {
5835 : SetDependsOnFlag(kExternalMemory);
5836 : SetDependsOnFlag(kTypedArrayElements);
5837 : } else {
5838 0 : UNREACHABLE();
5839 : }
5840 : // Native code could change the specialized array.
5841 : SetDependsOnFlag(kCalls);
5842 : }
5843 :
5844 : SetFlag(kUseGVN);
5845 52051 : }
5846 :
5847 15 : bool IsDeletable() const override { return !RequiresHoleCheck(); }
5848 :
5849 : // Establish some checks around our packed fields
5850 : enum LoadKeyedBits {
5851 : kBitsForElementsKind = 5,
5852 : kBitsForHoleMode = 2,
5853 : kBitsForBaseOffset = 24,
5854 : kBitsForIsDehoisted = 1,
5855 :
5856 : kStartElementsKind = 0,
5857 : kStartHoleMode = kStartElementsKind + kBitsForElementsKind,
5858 : kStartBaseOffset = kStartHoleMode + kBitsForHoleMode,
5859 : kStartIsDehoisted = kStartBaseOffset + kBitsForBaseOffset
5860 : };
5861 :
5862 : STATIC_ASSERT((kBitsForElementsKind + kBitsForHoleMode + kBitsForBaseOffset +
5863 : kBitsForIsDehoisted) <= sizeof(uint32_t) * 8);
5864 : STATIC_ASSERT(kElementsKindCount <= (1 << kBitsForElementsKind));
5865 : class ElementsKindField:
5866 : public BitField<ElementsKind, kStartElementsKind, kBitsForElementsKind>
5867 : {}; // NOLINT
5868 : class HoleModeField:
5869 : public BitField<LoadKeyedHoleMode, kStartHoleMode, kBitsForHoleMode>
5870 : {}; // NOLINT
5871 : class BaseOffsetField:
5872 : public BitField<uint32_t, kStartBaseOffset, kBitsForBaseOffset>
5873 : {}; // NOLINT
5874 : class IsDehoistedField:
5875 : public BitField<bool, kStartIsDehoisted, kBitsForIsDehoisted>
5876 : {}; // NOLINT
5877 : uint32_t bit_field_;
5878 : };
5879 :
5880 :
5881 : // Indicates whether the store is a store to an entry that was previously
5882 : // initialized or not.
5883 : enum StoreFieldOrKeyedMode {
5884 : // The entry could be either previously initialized or not.
5885 : INITIALIZING_STORE,
5886 : // At the time of this store it is guaranteed that the entry is already
5887 : // initialized.
5888 : STORE_TO_INITIALIZED_ENTRY
5889 : };
5890 :
5891 :
5892 0 : class HStoreNamedField final : public HTemplateInstruction<3> {
5893 : public:
5894 458194 : DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*,
5895 : HObjectAccess, HValue*);
5896 44968 : DECLARE_INSTRUCTION_FACTORY_P4(HStoreNamedField, HValue*,
5897 : HObjectAccess, HValue*, StoreFieldOrKeyedMode);
5898 :
5899 2667699 : DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
5900 :
5901 11314 : bool HasEscapingOperandAt(int index) override { return index == 1; }
5902 9325 : bool HasOutOfBoundsAccess(int size) override {
5903 18650 : return !access().IsInobject() || access().offset() >= size;
5904 : }
5905 671873 : Representation RequiredInputRepresentation(int index) override {
5906 789861 : if (index == 0 && access().IsExternalMemory()) {
5907 : // object must be external in case of external memory access
5908 : return Representation::External();
5909 601012 : } else if (index == 1) {
5910 449178 : if (field_representation().IsInteger8() ||
5911 224589 : field_representation().IsUInteger8() ||
5912 224589 : field_representation().IsInteger16() ||
5913 449178 : field_representation().IsUInteger16() ||
5914 : field_representation().IsInteger32()) {
5915 : return Representation::Integer32();
5916 211170 : } else if (field_representation().IsDouble()) {
5917 : return field_representation();
5918 210821 : } else if (field_representation().IsSmi()) {
5919 70861 : if (SmiValuesAre32Bits() &&
5920 : store_mode() == STORE_TO_INITIALIZED_ENTRY) {
5921 : return Representation::Integer32();
5922 : }
5923 : return field_representation();
5924 139960 : } else if (field_representation().IsExternal()) {
5925 : return Representation::External();
5926 : }
5927 : }
5928 : return Representation::Tagged();
5929 : }
5930 237985 : bool HandleSideEffectDominator(GVNFlag side_effect,
5931 : HValue* dominator) override {
5932 : DCHECK(side_effect == kNewSpacePromotion);
5933 237985 : if (!FLAG_use_write_barrier_elimination) return false;
5934 237985 : dominator_ = dominator;
5935 237985 : return false;
5936 : }
5937 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
5938 :
5939 : HValue* object() const { return OperandAt(0); }
5940 : HValue* value() const { return OperandAt(1); }
5941 : HValue* transition() const { return OperandAt(2); }
5942 :
5943 : HObjectAccess access() const { return access_; }
5944 : HValue* dominator() const { return dominator_; }
5945 : bool has_transition() const { return HasTransitionField::decode(bit_field_); }
5946 : StoreFieldOrKeyedMode store_mode() const {
5947 : return StoreModeField::decode(bit_field_);
5948 : }
5949 :
5950 9704 : Handle<Map> transition_map() const {
5951 9704 : if (has_transition()) {
5952 : return Handle<Map>::cast(
5953 19408 : HConstant::cast(transition())->handle(isolate()));
5954 : } else {
5955 0 : return Handle<Map>();
5956 : }
5957 : }
5958 :
5959 11394 : void SetTransition(HConstant* transition) {
5960 : DCHECK(!has_transition()); // Only set once.
5961 11394 : SetOperandAt(2, transition);
5962 22788 : bit_field_ = HasTransitionField::update(bit_field_, true);
5963 : SetChangesFlag(kMaps);
5964 11394 : }
5965 :
5966 490814 : bool NeedsWriteBarrier() const {
5967 : DCHECK(!field_representation().IsDouble() ||
5968 : (FLAG_unbox_double_fields && access_.IsInobject()) ||
5969 : !has_transition());
5970 357703 : if (field_representation().IsDouble()) return false;
5971 357157 : if (field_representation().IsSmi()) return false;
5972 273890 : if (field_representation().IsInteger32()) return false;
5973 247923 : if (field_representation().IsExternal()) return false;
5974 381034 : return StoringValueNeedsWriteBarrier(value()) &&
5975 381034 : ReceiverObjectNeedsWriteBarrier(object(), value(), dominator());
5976 : }
5977 :
5978 20809 : bool NeedsWriteBarrierForMap() {
5979 : return ReceiverObjectNeedsWriteBarrier(object(), transition(),
5980 20809 : dominator());
5981 : }
5982 :
5983 : SmiCheck SmiCheckForWriteBarrier() const {
5984 14802 : if (field_representation().IsHeapObject()) return OMIT_SMI_CHECK;
5985 5084 : if (value()->type().IsHeapObject()) return OMIT_SMI_CHECK;
5986 : return INLINE_SMI_CHECK;
5987 : }
5988 :
5989 14802 : PointersToHereCheck PointersToHereCheckForValue() const {
5990 14802 : return PointersToHereCheckForObject(value(), dominator());
5991 : }
5992 :
5993 : Representation field_representation() const {
5994 939410 : return access_.representation();
5995 : }
5996 :
5997 : void UpdateValue(HValue* value) {
5998 : SetOperandAt(1, value);
5999 : }
6000 :
6001 290 : bool CanBeReplacedWith(HStoreNamedField* that) const {
6002 290 : if (!this->access().Equals(that->access())) return false;
6003 0 : if (SmiValuesAre32Bits() &&
6004 0 : this->field_representation().IsSmi() &&
6005 0 : this->store_mode() == INITIALIZING_STORE &&
6006 : that->store_mode() == STORE_TO_INITIALIZED_ENTRY) {
6007 : // We cannot replace an initializing store to a smi field with a store to
6008 : // an initialized entry on 64-bit architectures (with 32-bit smis).
6009 : return false;
6010 : }
6011 0 : return true;
6012 : }
6013 :
6014 : private:
6015 251581 : HStoreNamedField(HValue* obj, HObjectAccess access, HValue* val,
6016 : StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE)
6017 : : access_(access),
6018 : dominator_(NULL),
6019 : bit_field_(HasTransitionField::encode(false) |
6020 503162 : StoreModeField::encode(store_mode)) {
6021 : // Stores to a non existing in-object property are allowed only to the
6022 : // newly allocated objects (via HAllocate or HInnerAllocatedObject).
6023 : DCHECK(!access.IsInobject() || access.existing_inobject_property() ||
6024 : obj->IsAllocate() || obj->IsInnerAllocatedObject());
6025 251581 : SetOperandAt(0, obj);
6026 251581 : SetOperandAt(1, val);
6027 251581 : SetOperandAt(2, obj);
6028 251581 : access.SetGVNFlags(this, STORE);
6029 251581 : }
6030 :
6031 : class HasTransitionField : public BitField<bool, 0, 1> {};
6032 : class StoreModeField : public BitField<StoreFieldOrKeyedMode, 1, 1> {};
6033 :
6034 : HObjectAccess access_;
6035 : HValue* dominator_;
6036 : uint32_t bit_field_;
6037 : };
6038 :
6039 0 : class HStoreKeyed final : public HTemplateInstruction<4>,
6040 : public ArrayInstructionInterface {
6041 : public:
6042 39370 : DECLARE_INSTRUCTION_FACTORY_P5(HStoreKeyed, HValue*, HValue*, HValue*,
6043 : HValue*, ElementsKind);
6044 17146 : DECLARE_INSTRUCTION_FACTORY_P6(HStoreKeyed, HValue*, HValue*, HValue*,
6045 : HValue*, ElementsKind, StoreFieldOrKeyedMode);
6046 : DECLARE_INSTRUCTION_FACTORY_P7(HStoreKeyed, HValue*, HValue*, HValue*,
6047 : HValue*, ElementsKind, StoreFieldOrKeyedMode,
6048 : int);
6049 :
6050 229454 : Representation RequiredInputRepresentation(int index) override {
6051 : // kind_fast: tagged[int32] = tagged
6052 : // kind_double: tagged[int32] = double
6053 : // kind_smi : tagged[int32] = smi
6054 : // kind_fixed_typed_array: tagged[int32] = (double | int32)
6055 : // kind_external: external[int32] = (double | int32)
6056 151721 : if (index == 0) {
6057 : return is_fixed_typed_array() ? Representation::External()
6058 43669 : : Representation::Tagged();
6059 108052 : } else if (index == 1) {
6060 : return ArrayInstructionInterface::KeyedAccessIndexRequirement(
6061 : OperandAt(1)->representation());
6062 76032 : } else if (index == 2) {
6063 34064 : return RequiredValueRepresentation(elements_kind(), store_mode());
6064 : }
6065 :
6066 : DCHECK_EQ(3, index);
6067 : return HasBackingStoreOwner() ? Representation::Tagged()
6068 41968 : : Representation::None();
6069 : }
6070 :
6071 40026 : static Representation RequiredValueRepresentation(
6072 : ElementsKind kind, StoreFieldOrKeyedMode mode) {
6073 40026 : if (IsDoubleOrFloatElementsKind(kind)) {
6074 : return Representation::Double();
6075 : }
6076 :
6077 32698 : if (kind == FAST_SMI_ELEMENTS && SmiValuesAre32Bits() &&
6078 : mode == STORE_TO_INITIALIZED_ENTRY) {
6079 : return Representation::Integer32();
6080 : }
6081 :
6082 30201 : if (IsFastSmiElementsKind(kind)) {
6083 : return Representation::Smi();
6084 : }
6085 :
6086 20296 : if (IsFixedTypedArrayElementsKind(kind)) {
6087 : return Representation::Integer32();
6088 : }
6089 : return Representation::Tagged();
6090 : }
6091 :
6092 13 : bool is_fixed_typed_array() const {
6093 13 : return IsFixedTypedArrayElementsKind(elements_kind());
6094 : }
6095 :
6096 29332 : Representation observed_input_representation(int index) override {
6097 25976 : if (index != 2) return RequiredInputRepresentation(index);
6098 3356 : if (IsUninitialized()) {
6099 : return Representation::None();
6100 : }
6101 : Representation r =
6102 3356 : RequiredValueRepresentation(elements_kind(), store_mode());
6103 : // For fast object elements kinds, don't assume anything.
6104 3356 : if (r.IsTagged()) return Representation::None();
6105 603 : return r;
6106 : }
6107 :
6108 : HValue* elements() const { return OperandAt(0); }
6109 : HValue* key() const { return OperandAt(1); }
6110 12 : HValue* value() const { return OperandAt(2); }
6111 : HValue* backing_store_owner() const {
6112 : DCHECK(HasBackingStoreOwner());
6113 : return OperandAt(3);
6114 : }
6115 : bool HasBackingStoreOwner() const { return OperandAt(0) != OperandAt(3); }
6116 : bool value_is_smi() const { return IsFastSmiElementsKind(elements_kind()); }
6117 : StoreFieldOrKeyedMode store_mode() const {
6118 : return StoreModeField::decode(bit_field_);
6119 : }
6120 2870 : ElementsKind elements_kind() const override {
6121 35501 : return ElementsKindField::decode(bit_field_);
6122 : }
6123 : uint32_t base_offset() const { return base_offset_; }
6124 : bool TryIncreaseBaseOffset(uint32_t increase_by_value) override;
6125 56228 : HValue* GetKey() override { return key(); }
6126 1199 : void SetKey(HValue* key) override { SetOperandAt(1, key); }
6127 0 : bool IsDehoisted() const override {
6128 0 : return IsDehoistedField::decode(bit_field_);
6129 : }
6130 1199 : void SetDehoisted(bool is_dehoisted) override {
6131 2398 : bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
6132 1199 : }
6133 : bool IsUninitialized() { return IsUninitializedField::decode(bit_field_); }
6134 : void SetUninitialized(bool is_uninitialized) {
6135 : bit_field_ = IsUninitializedField::update(bit_field_, is_uninitialized);
6136 : }
6137 :
6138 : bool IsConstantHoleStore() {
6139 : return value()->IsConstant() && HConstant::cast(value())->IsTheHole();
6140 : }
6141 :
6142 13771 : bool HandleSideEffectDominator(GVNFlag side_effect,
6143 : HValue* dominator) override {
6144 : DCHECK(side_effect == kNewSpacePromotion);
6145 13771 : dominator_ = dominator;
6146 13771 : return false;
6147 : }
6148 :
6149 : HValue* dominator() const { return dominator_; }
6150 :
6151 70748 : bool NeedsWriteBarrier() {
6152 46152 : if (value_is_smi()) {
6153 : return false;
6154 : } else {
6155 53578 : return StoringValueNeedsWriteBarrier(value()) &&
6156 53578 : ReceiverObjectNeedsWriteBarrier(elements(), value(), dominator());
6157 : }
6158 : }
6159 :
6160 6530 : PointersToHereCheck PointersToHereCheckForValue() const {
6161 6530 : return PointersToHereCheckForObject(value(), dominator());
6162 : }
6163 :
6164 : bool NeedsCanonicalization();
6165 :
6166 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
6167 :
6168 403648 : DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)
6169 :
6170 : private:
6171 28258 : HStoreKeyed(HValue* obj, HValue* key, HValue* val,
6172 : HValue* backing_store_owner, ElementsKind elements_kind,
6173 : StoreFieldOrKeyedMode store_mode = INITIALIZING_STORE,
6174 13640 : int offset = kDefaultKeyedHeaderOffsetSentinel)
6175 : : base_offset_(offset == kDefaultKeyedHeaderOffsetSentinel
6176 28258 : ? GetDefaultHeaderSizeForElementsKind(elements_kind)
6177 : : offset),
6178 : bit_field_(IsDehoistedField::encode(false) |
6179 : IsUninitializedField::encode(false) |
6180 28258 : StoreModeField::encode(store_mode) |
6181 : ElementsKindField::encode(elements_kind)),
6182 84774 : dominator_(NULL) {
6183 28258 : SetOperandAt(0, obj);
6184 28258 : SetOperandAt(1, key);
6185 28258 : SetOperandAt(2, val);
6186 28258 : SetOperandAt(3, backing_store_owner != nullptr ? backing_store_owner : obj);
6187 : DCHECK_EQ(HasBackingStoreOwner(), is_fixed_typed_array());
6188 :
6189 28258 : if (IsFastObjectElementsKind(elements_kind)) {
6190 : SetFlag(kTrackSideEffectDominators);
6191 : SetDependsOnFlag(kNewSpacePromotion);
6192 : }
6193 28258 : if (IsFastDoubleElementsKind(elements_kind)) {
6194 : SetChangesFlag(kDoubleArrayElements);
6195 22287 : } else if (IsFastSmiElementsKind(elements_kind)) {
6196 : SetChangesFlag(kArrayElements);
6197 13640 : } else if (is_fixed_typed_array()) {
6198 : SetChangesFlag(kTypedArrayElements);
6199 : SetChangesFlag(kExternalMemory);
6200 : SetFlag(kTruncatingToNumber);
6201 : } else {
6202 : SetChangesFlag(kArrayElements);
6203 : }
6204 :
6205 : // {UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
6206 28258 : if (elements_kind >= UINT8_ELEMENTS && elements_kind <= INT32_ELEMENTS) {
6207 : SetFlag(kTruncatingToInt32);
6208 : }
6209 28258 : }
6210 :
6211 : class IsDehoistedField : public BitField<bool, 0, 1> {};
6212 : class IsUninitializedField : public BitField<bool, 1, 1> {};
6213 : class StoreModeField : public BitField<StoreFieldOrKeyedMode, 2, 1> {};
6214 : class ElementsKindField : public BitField<ElementsKind, 3, 5> {};
6215 :
6216 : uint32_t base_offset_;
6217 : uint32_t bit_field_;
6218 : HValue* dominator_;
6219 : };
6220 :
6221 0 : class HTransitionElementsKind final : public HTemplateInstruction<2> {
6222 : public:
6223 806 : inline static HTransitionElementsKind* New(Isolate* isolate, Zone* zone,
6224 : HValue* context, HValue* object,
6225 : Handle<Map> original_map,
6226 : Handle<Map> transitioned_map) {
6227 : return new(zone) HTransitionElementsKind(context, object,
6228 1612 : original_map, transitioned_map);
6229 : }
6230 :
6231 1687 : Representation RequiredInputRepresentation(int index) override {
6232 1687 : return Representation::Tagged();
6233 : }
6234 :
6235 : HValue* object() const { return OperandAt(0); }
6236 : HValue* context() const { return OperandAt(1); }
6237 : Unique<Map> original_map() const { return original_map_; }
6238 : Unique<Map> transitioned_map() const { return transitioned_map_; }
6239 : ElementsKind from_kind() const {
6240 : return FromElementsKindField::decode(bit_field_);
6241 : }
6242 : ElementsKind to_kind() const {
6243 : return ToElementsKindField::decode(bit_field_);
6244 : }
6245 : bool map_is_stable() const { return MapIsStableField::decode(bit_field_); }
6246 :
6247 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
6248 :
6249 19258 : DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
6250 :
6251 : protected:
6252 610 : bool DataEquals(HValue* other) override {
6253 : HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
6254 647 : return original_map_ == instr->original_map_ &&
6255 647 : transitioned_map_ == instr->transitioned_map_;
6256 : }
6257 :
6258 1508 : int RedefinedOperandIndex() override { return 0; }
6259 :
6260 : private:
6261 806 : HTransitionElementsKind(HValue* context, HValue* object,
6262 : Handle<Map> original_map,
6263 806 : Handle<Map> transitioned_map)
6264 : : original_map_(Unique<Map>(original_map)),
6265 : transitioned_map_(Unique<Map>(transitioned_map)),
6266 : bit_field_(
6267 806 : FromElementsKindField::encode(original_map->elements_kind()) |
6268 806 : ToElementsKindField::encode(transitioned_map->elements_kind()) |
6269 1612 : MapIsStableField::encode(transitioned_map->is_stable())) {
6270 806 : SetOperandAt(0, object);
6271 806 : SetOperandAt(1, context);
6272 : SetFlag(kUseGVN);
6273 : SetChangesFlag(kElementsKind);
6274 806 : if (!IsSimpleMapChangeTransition(from_kind(), to_kind())) {
6275 : SetChangesFlag(kElementsPointer);
6276 : SetChangesFlag(kNewSpacePromotion);
6277 : }
6278 : set_representation(Representation::Tagged());
6279 806 : }
6280 :
6281 : class FromElementsKindField : public BitField<ElementsKind, 0, 5> {};
6282 : class ToElementsKindField : public BitField<ElementsKind, 5, 5> {};
6283 : class MapIsStableField : public BitField<bool, 10, 1> {};
6284 :
6285 : Unique<Map> original_map_;
6286 : Unique<Map> transitioned_map_;
6287 : uint32_t bit_field_;
6288 : };
6289 :
6290 :
6291 0 : class HStringAdd final : public HBinaryOperation {
6292 : public:
6293 : static HInstruction* New(
6294 : Isolate* isolate, Zone* zone, HValue* context, HValue* left,
6295 : HValue* right, PretenureFlag pretenure_flag = NOT_TENURED,
6296 : StringAddFlags flags = STRING_ADD_CHECK_BOTH,
6297 : Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null());
6298 :
6299 : StringAddFlags flags() const { return flags_; }
6300 : PretenureFlag pretenure_flag() const { return pretenure_flag_; }
6301 :
6302 73453 : Representation RequiredInputRepresentation(int index) override {
6303 73453 : return Representation::Tagged();
6304 : }
6305 :
6306 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
6307 :
6308 1115981 : DECLARE_CONCRETE_INSTRUCTION(StringAdd)
6309 :
6310 : protected:
6311 30 : bool DataEquals(HValue* other) override {
6312 60 : return flags_ == HStringAdd::cast(other)->flags_ &&
6313 60 : pretenure_flag_ == HStringAdd::cast(other)->pretenure_flag_;
6314 : }
6315 :
6316 : private:
6317 26857 : HStringAdd(HValue* context, HValue* left, HValue* right,
6318 : PretenureFlag pretenure_flag, StringAddFlags flags,
6319 : Handle<AllocationSite> allocation_site)
6320 : : HBinaryOperation(context, left, right, HType::String()),
6321 : flags_(flags),
6322 26857 : pretenure_flag_(pretenure_flag) {
6323 : set_representation(Representation::Tagged());
6324 26857 : if ((flags & STRING_ADD_CONVERT) == STRING_ADD_CONVERT) {
6325 : SetAllSideEffects();
6326 : ClearFlag(kUseGVN);
6327 : } else {
6328 : SetChangesFlag(kNewSpacePromotion);
6329 : SetFlag(kUseGVN);
6330 : }
6331 : SetDependsOnFlag(kMaps);
6332 26857 : if (FLAG_trace_pretenuring) {
6333 : PrintF("HStringAdd with AllocationSite %p %s\n",
6334 : allocation_site.is_null()
6335 : ? static_cast<void*>(NULL)
6336 : : static_cast<void*>(*allocation_site),
6337 0 : pretenure_flag == TENURED ? "tenured" : "not tenured");
6338 : }
6339 26857 : }
6340 :
6341 48 : bool IsDeletable() const final {
6342 48 : return (flags_ & STRING_ADD_CONVERT) != STRING_ADD_CONVERT;
6343 : }
6344 :
6345 : const StringAddFlags flags_;
6346 : const PretenureFlag pretenure_flag_;
6347 : };
6348 :
6349 :
6350 0 : class HStringCharCodeAt final : public HTemplateInstruction<3> {
6351 : public:
6352 377 : DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HStringCharCodeAt,
6353 : HValue*,
6354 : HValue*);
6355 :
6356 1179 : Representation RequiredInputRepresentation(int index) override {
6357 : // The index is supposed to be Integer32.
6358 : return index == 2
6359 : ? Representation::Integer32()
6360 1179 : : Representation::Tagged();
6361 : }
6362 :
6363 : HValue* context() const { return OperandAt(0); }
6364 : HValue* string() const { return OperandAt(1); }
6365 : HValue* index() const { return OperandAt(2); }
6366 :
6367 14715 : DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
6368 :
6369 : protected:
6370 0 : bool DataEquals(HValue* other) override { return true; }
6371 :
6372 377 : Range* InferRange(Zone* zone) override {
6373 377 : return new(zone) Range(0, String::kMaxUtf16CodeUnit);
6374 : }
6375 :
6376 : private:
6377 754 : HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
6378 377 : SetOperandAt(0, context);
6379 377 : SetOperandAt(1, string);
6380 377 : SetOperandAt(2, index);
6381 : set_representation(Representation::Integer32());
6382 : SetFlag(kUseGVN);
6383 : SetDependsOnFlag(kMaps);
6384 : SetDependsOnFlag(kStringChars);
6385 : SetChangesFlag(kNewSpacePromotion);
6386 377 : }
6387 :
6388 : // No side effects: runtime function assumes string + number inputs.
6389 0 : bool IsDeletable() const override { return true; }
6390 : };
6391 :
6392 :
6393 0 : class HStringCharFromCode final : public HTemplateInstruction<2> {
6394 : public:
6395 : static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
6396 : HValue* char_code);
6397 :
6398 1084 : Representation RequiredInputRepresentation(int index) override {
6399 : return index == 0
6400 : ? Representation::Tagged()
6401 1084 : : Representation::Integer32();
6402 : }
6403 :
6404 : HValue* context() const { return OperandAt(0); }
6405 : HValue* value() const { return OperandAt(1); }
6406 :
6407 18 : bool DataEquals(HValue* other) override { return true; }
6408 :
6409 119995 : DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
6410 :
6411 : private:
6412 506 : HStringCharFromCode(HValue* context, HValue* char_code)
6413 506 : : HTemplateInstruction<2>(HType::String()) {
6414 506 : SetOperandAt(0, context);
6415 506 : SetOperandAt(1, char_code);
6416 : set_representation(Representation::Tagged());
6417 : SetFlag(kUseGVN);
6418 : SetChangesFlag(kNewSpacePromotion);
6419 506 : }
6420 :
6421 0 : bool IsDeletable() const override {
6422 0 : return !value()->ToNumberCanBeObserved();
6423 : }
6424 : };
6425 :
6426 :
6427 0 : class HTypeof final : public HTemplateInstruction<2> {
6428 : public:
6429 40359 : DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HTypeof, HValue*);
6430 :
6431 : HValue* context() const { return OperandAt(0); }
6432 : HValue* value() const { return OperandAt(1); }
6433 :
6434 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
6435 :
6436 91503 : Representation RequiredInputRepresentation(int index) override {
6437 91503 : return Representation::Tagged();
6438 : }
6439 :
6440 982565 : DECLARE_CONCRETE_INSTRUCTION(Typeof)
6441 :
6442 : private:
6443 80718 : explicit HTypeof(HValue* context, HValue* value) {
6444 40359 : SetOperandAt(0, context);
6445 40359 : SetOperandAt(1, value);
6446 : set_representation(Representation::Tagged());
6447 40359 : }
6448 :
6449 28 : bool IsDeletable() const override { return true; }
6450 : };
6451 :
6452 :
6453 0 : class HTrapAllocationMemento final : public HTemplateInstruction<1> {
6454 : public:
6455 37 : DECLARE_INSTRUCTION_FACTORY_P1(HTrapAllocationMemento, HValue*);
6456 :
6457 37 : Representation RequiredInputRepresentation(int index) override {
6458 37 : return Representation::Tagged();
6459 : }
6460 :
6461 : HValue* object() { return OperandAt(0); }
6462 :
6463 444 : DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento)
6464 :
6465 : private:
6466 74 : explicit HTrapAllocationMemento(HValue* obj) {
6467 37 : SetOperandAt(0, obj);
6468 37 : }
6469 : };
6470 :
6471 :
6472 0 : class HMaybeGrowElements final : public HTemplateInstruction<5> {
6473 : public:
6474 2606 : DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P6(HMaybeGrowElements, HValue*,
6475 : HValue*, HValue*, HValue*, bool,
6476 : ElementsKind);
6477 :
6478 13380 : Representation RequiredInputRepresentation(int index) override {
6479 13380 : if (index < 3) {
6480 : return Representation::Tagged();
6481 : }
6482 : DCHECK(index == 3 || index == 4);
6483 : return Representation::Integer32();
6484 : }
6485 :
6486 : HValue* context() const { return OperandAt(0); }
6487 : HValue* object() const { return OperandAt(1); }
6488 : HValue* elements() const { return OperandAt(2); }
6489 : HValue* key() const { return OperandAt(3); }
6490 : HValue* current_capacity() const { return OperandAt(4); }
6491 :
6492 : bool is_js_array() const { return is_js_array_; }
6493 : ElementsKind kind() const { return kind_; }
6494 :
6495 107999 : DECLARE_CONCRETE_INSTRUCTION(MaybeGrowElements)
6496 :
6497 : protected:
6498 0 : bool DataEquals(HValue* other) override { return true; }
6499 :
6500 : private:
6501 2606 : explicit HMaybeGrowElements(HValue* context, HValue* object, HValue* elements,
6502 : HValue* key, HValue* current_capacity,
6503 2606 : bool is_js_array, ElementsKind kind) {
6504 2606 : is_js_array_ = is_js_array;
6505 2606 : kind_ = kind;
6506 :
6507 2606 : SetOperandAt(0, context);
6508 2606 : SetOperandAt(1, object);
6509 2606 : SetOperandAt(2, elements);
6510 2606 : SetOperandAt(3, key);
6511 2606 : SetOperandAt(4, current_capacity);
6512 :
6513 : SetFlag(kUseGVN);
6514 : SetChangesFlag(kElementsPointer);
6515 : SetChangesFlag(kNewSpacePromotion);
6516 : set_representation(Representation::Tagged());
6517 2606 : }
6518 :
6519 : bool is_js_array_;
6520 : ElementsKind kind_;
6521 : };
6522 :
6523 :
6524 0 : class HSeqStringGetChar final : public HTemplateInstruction<2> {
6525 : public:
6526 : static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
6527 : String::Encoding encoding, HValue* string,
6528 : HValue* index);
6529 :
6530 31788 : Representation RequiredInputRepresentation(int index) override {
6531 : return (index == 0) ? Representation::Tagged()
6532 31788 : : Representation::Integer32();
6533 : }
6534 :
6535 : String::Encoding encoding() const { return encoding_; }
6536 : HValue* string() const { return OperandAt(0); }
6537 : HValue* index() const { return OperandAt(1); }
6538 :
6539 306064 : DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar)
6540 :
6541 : protected:
6542 0 : bool DataEquals(HValue* other) override {
6543 0 : return encoding() == HSeqStringGetChar::cast(other)->encoding();
6544 : }
6545 :
6546 14320 : Range* InferRange(Zone* zone) override {
6547 14320 : if (encoding() == String::ONE_BYTE_ENCODING) {
6548 7160 : return new(zone) Range(0, String::kMaxOneByteCharCode);
6549 : } else {
6550 : DCHECK_EQ(String::TWO_BYTE_ENCODING, encoding());
6551 7160 : return new(zone) Range(0, String::kMaxUtf16CodeUnit);
6552 : }
6553 : }
6554 :
6555 : private:
6556 14320 : HSeqStringGetChar(String::Encoding encoding,
6557 : HValue* string,
6558 14320 : HValue* index) : encoding_(encoding) {
6559 14320 : SetOperandAt(0, string);
6560 14320 : SetOperandAt(1, index);
6561 : set_representation(Representation::Integer32());
6562 : SetFlag(kUseGVN);
6563 : SetDependsOnFlag(kStringChars);
6564 14320 : }
6565 :
6566 0 : bool IsDeletable() const override { return true; }
6567 :
6568 : String::Encoding encoding_;
6569 : };
6570 :
6571 :
6572 0 : class HSeqStringSetChar final : public HTemplateInstruction<4> {
6573 : public:
6574 14320 : DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(
6575 : HSeqStringSetChar, String::Encoding,
6576 : HValue*, HValue*, HValue*);
6577 :
6578 : String::Encoding encoding() { return encoding_; }
6579 : HValue* context() { return OperandAt(0); }
6580 : HValue* string() { return OperandAt(1); }
6581 : HValue* index() { return OperandAt(2); }
6582 : HValue* value() { return OperandAt(3); }
6583 :
6584 57280 : Representation RequiredInputRepresentation(int index) override {
6585 : return (index <= 1) ? Representation::Tagged()
6586 57280 : : Representation::Integer32();
6587 : }
6588 :
6589 243232 : DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar)
6590 :
6591 : private:
6592 14320 : HSeqStringSetChar(HValue* context,
6593 : String::Encoding encoding,
6594 : HValue* string,
6595 : HValue* index,
6596 14320 : HValue* value) : encoding_(encoding) {
6597 14320 : SetOperandAt(0, context);
6598 14320 : SetOperandAt(1, string);
6599 14320 : SetOperandAt(2, index);
6600 14320 : SetOperandAt(3, value);
6601 : set_representation(Representation::Tagged());
6602 : SetChangesFlag(kStringChars);
6603 14320 : }
6604 :
6605 : String::Encoding encoding_;
6606 : };
6607 :
6608 :
6609 0 : class HCheckMapValue final : public HTemplateInstruction<2> {
6610 : public:
6611 1436 : DECLARE_INSTRUCTION_FACTORY_P2(HCheckMapValue, HValue*, HValue*);
6612 :
6613 1583 : Representation RequiredInputRepresentation(int index) override {
6614 1583 : return Representation::Tagged();
6615 : }
6616 :
6617 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
6618 :
6619 757 : HType CalculateInferredType() override {
6620 757 : if (value()->type().IsHeapObject()) return value()->type();
6621 : return HType::HeapObject();
6622 : }
6623 :
6624 : HValue* value() const { return OperandAt(0); }
6625 : HValue* map() const { return OperandAt(1); }
6626 :
6627 : HValue* Canonicalize() override;
6628 :
6629 22256 : DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
6630 :
6631 : protected:
6632 2424 : int RedefinedOperandIndex() override { return 0; }
6633 :
6634 139 : bool DataEquals(HValue* other) override { return true; }
6635 :
6636 : private:
6637 1436 : HCheckMapValue(HValue* value, HValue* map)
6638 1436 : : HTemplateInstruction<2>(HType::HeapObject()) {
6639 1436 : SetOperandAt(0, value);
6640 1436 : SetOperandAt(1, map);
6641 : set_representation(Representation::Tagged());
6642 : SetFlag(kUseGVN);
6643 : SetDependsOnFlag(kMaps);
6644 : SetDependsOnFlag(kElementsKind);
6645 1436 : }
6646 : };
6647 :
6648 :
6649 0 : class HForInPrepareMap final : public HTemplateInstruction<2> {
6650 : public:
6651 842 : DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HForInPrepareMap, HValue*);
6652 :
6653 1525 : Representation RequiredInputRepresentation(int index) override {
6654 1525 : return Representation::Tagged();
6655 : }
6656 :
6657 : HValue* context() const { return OperandAt(0); }
6658 : HValue* enumerable() const { return OperandAt(1); }
6659 :
6660 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
6661 :
6662 757 : HType CalculateInferredType() override { return HType::Tagged(); }
6663 :
6664 450986 : DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
6665 :
6666 : private:
6667 842 : HForInPrepareMap(HValue* context,
6668 842 : HValue* object) {
6669 842 : SetOperandAt(0, context);
6670 842 : SetOperandAt(1, object);
6671 : set_representation(Representation::Tagged());
6672 : SetAllSideEffects();
6673 842 : }
6674 : };
6675 :
6676 :
6677 0 : class HForInCacheArray final : public HTemplateInstruction<2> {
6678 : public:
6679 1914 : DECLARE_INSTRUCTION_FACTORY_P3(HForInCacheArray, HValue*, HValue*, int);
6680 :
6681 3505 : Representation RequiredInputRepresentation(int index) override {
6682 3505 : return Representation::Tagged();
6683 : }
6684 :
6685 : HValue* enumerable() const { return OperandAt(0); }
6686 : HValue* map() const { return OperandAt(1); }
6687 : int idx() const { return idx_; }
6688 :
6689 : HForInCacheArray* index_cache() {
6690 : return index_cache_;
6691 : }
6692 :
6693 : void set_index_cache(HForInCacheArray* index_cache) {
6694 842 : index_cache_ = index_cache;
6695 : }
6696 :
6697 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
6698 :
6699 1738 : HType CalculateInferredType() override { return HType::Tagged(); }
6700 :
6701 285721 : DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
6702 :
6703 : private:
6704 1914 : HForInCacheArray(HValue* enumerable,
6705 : HValue* keys,
6706 1914 : int idx) : idx_(idx) {
6707 1914 : SetOperandAt(0, enumerable);
6708 1914 : SetOperandAt(1, keys);
6709 : set_representation(Representation::Tagged());
6710 1914 : }
6711 :
6712 : int idx_;
6713 : HForInCacheArray* index_cache_;
6714 : };
6715 :
6716 :
6717 0 : class HLoadFieldByIndex final : public HTemplateInstruction<2> {
6718 : public:
6719 : DECLARE_INSTRUCTION_FACTORY_P2(HLoadFieldByIndex, HValue*, HValue*);
6720 :
6721 594 : HLoadFieldByIndex(HValue* object,
6722 594 : HValue* index) {
6723 594 : SetOperandAt(0, object);
6724 594 : SetOperandAt(1, index);
6725 : SetChangesFlag(kNewSpacePromotion);
6726 : set_representation(Representation::Tagged());
6727 594 : }
6728 :
6729 0 : Representation RequiredInputRepresentation(int index) override {
6730 0 : if (index == 1) {
6731 : return Representation::Smi();
6732 : } else {
6733 : return Representation::Tagged();
6734 : }
6735 : }
6736 :
6737 : HValue* object() const { return OperandAt(0); }
6738 : HValue* index() const { return OperandAt(1); }
6739 :
6740 : std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
6741 :
6742 0 : HType CalculateInferredType() override { return HType::Tagged(); }
6743 :
6744 171528 : DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
6745 :
6746 : private:
6747 1 : bool IsDeletable() const override { return true; }
6748 : };
6749 :
6750 : #undef DECLARE_INSTRUCTION
6751 : #undef DECLARE_CONCRETE_INSTRUCTION
6752 :
6753 : } // namespace internal
6754 : } // namespace v8
6755 :
6756 : #endif // V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_
|