The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / hydrogen-instructions.h @ f230a1cf

History | View | Annotate | Download (220 KB)

1
// Copyright 2012 the V8 project authors. All rights reserved.
2
// Redistribution and use in source and binary forms, with or without
3
// modification, are permitted provided that the following conditions are
4
// met:
5
//
6
//     * Redistributions of source code must retain the above copyright
7
//       notice, this list of conditions and the following disclaimer.
8
//     * Redistributions in binary form must reproduce the above
9
//       copyright notice, this list of conditions and the following
10
//       disclaimer in the documentation and/or other materials provided
11
//       with the distribution.
12
//     * Neither the name of Google Inc. nor the names of its
13
//       contributors may be used to endorse or promote products derived
14
//       from this software without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27

    
28
#ifndef V8_HYDROGEN_INSTRUCTIONS_H_
29
#define V8_HYDROGEN_INSTRUCTIONS_H_
30

    
31
#include "v8.h"
32

    
33
#include "allocation.h"
34
#include "code-stubs.h"
35
#include "data-flow.h"
36
#include "deoptimizer.h"
37
#include "small-pointer-list.h"
38
#include "string-stream.h"
39
#include "unique.h"
40
#include "v8conversions.h"
41
#include "v8utils.h"
42
#include "zone.h"
43

    
44
namespace v8 {
45
namespace internal {
46

    
47
// Forward declarations.
48
class HBasicBlock;
49
class HEnvironment;
50
class HInferRepresentationPhase;
51
class HInstruction;
52
class HLoopInformation;
53
class HStoreNamedField;
54
class HValue;
55
class LInstruction;
56
class LChunkBuilder;
57

    
58
#define HYDROGEN_ABSTRACT_INSTRUCTION_LIST(V)  \
59
  V(ArithmeticBinaryOperation)                 \
60
  V(BinaryOperation)                           \
61
  V(BitwiseBinaryOperation)                    \
62
  V(ControlInstruction)                        \
63
  V(Instruction)                               \
64

    
65

    
66
#define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)  \
67
  V(AbnormalExit)                              \
68
  V(AccessArgumentsAt)                         \
69
  V(Add)                                       \
70
  V(Allocate)                                  \
71
  V(ApplyArguments)                            \
72
  V(ArgumentsElements)                         \
73
  V(ArgumentsLength)                           \
74
  V(ArgumentsObject)                           \
75
  V(Bitwise)                                   \
76
  V(BlockEntry)                                \
77
  V(BoundsCheck)                               \
78
  V(BoundsCheckBaseIndexInformation)           \
79
  V(Branch)                                    \
80
  V(CallConstantFunction)                      \
81
  V(CallFunction)                              \
82
  V(CallGlobal)                                \
83
  V(CallKeyed)                                 \
84
  V(CallKnownGlobal)                           \
85
  V(CallNamed)                                 \
86
  V(CallNew)                                   \
87
  V(CallNewArray)                              \
88
  V(CallRuntime)                               \
89
  V(CallStub)                                  \
90
  V(CapturedObject)                            \
91
  V(Change)                                    \
92
  V(CheckHeapObject)                           \
93
  V(CheckInstanceType)                         \
94
  V(CheckMaps)                                 \
95
  V(CheckMapValue)                             \
96
  V(CheckSmi)                                  \
97
  V(CheckValue)                                \
98
  V(ClampToUint8)                              \
99
  V(ClassOfTestAndBranch)                      \
100
  V(CompareNumericAndBranch)                   \
101
  V(CompareHoleAndBranch)                      \
102
  V(CompareGeneric)                            \
103
  V(CompareObjectEqAndBranch)                  \
104
  V(CompareMap)                                \
105
  V(Constant)                                  \
106
  V(Context)                                   \
107
  V(DateField)                                 \
108
  V(DebugBreak)                                \
109
  V(DeclareGlobals)                            \
110
  V(Deoptimize)                                \
111
  V(Div)                                       \
112
  V(DummyUse)                                  \
113
  V(ElementsKind)                              \
114
  V(EnterInlined)                              \
115
  V(EnvironmentMarker)                         \
116
  V(ForceRepresentation)                       \
117
  V(ForInCacheArray)                           \
118
  V(ForInPrepareMap)                           \
119
  V(FunctionLiteral)                           \
120
  V(GetCachedArrayIndex)                       \
121
  V(GlobalObject)                              \
122
  V(GlobalReceiver)                            \
123
  V(Goto)                                      \
124
  V(HasCachedArrayIndexAndBranch)              \
125
  V(HasInstanceTypeAndBranch)                  \
126
  V(InnerAllocatedObject)                      \
127
  V(InstanceOf)                                \
128
  V(InstanceOfKnownGlobal)                     \
129
  V(InvokeFunction)                            \
130
  V(IsConstructCallAndBranch)                  \
131
  V(IsObjectAndBranch)                         \
132
  V(IsStringAndBranch)                         \
133
  V(IsSmiAndBranch)                            \
134
  V(IsUndetectableAndBranch)                   \
135
  V(LeaveInlined)                              \
136
  V(LoadContextSlot)                           \
137
  V(LoadExternalArrayPointer)                  \
138
  V(LoadFieldByIndex)                          \
139
  V(LoadFunctionPrototype)                     \
140
  V(LoadGlobalCell)                            \
141
  V(LoadGlobalGeneric)                         \
142
  V(LoadKeyed)                                 \
143
  V(LoadKeyedGeneric)                          \
144
  V(LoadNamedField)                            \
145
  V(LoadNamedGeneric)                          \
146
  V(LoadRoot)                                  \
147
  V(MapEnumLength)                             \
148
  V(MathFloorOfDiv)                            \
149
  V(MathMinMax)                                \
150
  V(Mod)                                       \
151
  V(Mul)                                       \
152
  V(OsrEntry)                                  \
153
  V(OuterContext)                              \
154
  V(Parameter)                                 \
155
  V(Power)                                     \
156
  V(PushArgument)                              \
157
  V(Random)                                    \
158
  V(RegExpLiteral)                             \
159
  V(Return)                                    \
160
  V(Ror)                                       \
161
  V(Sar)                                       \
162
  V(SeqStringSetChar)                          \
163
  V(Shl)                                       \
164
  V(Shr)                                       \
165
  V(Simulate)                                  \
166
  V(StackCheck)                                \
167
  V(StoreCodeEntry)                            \
168
  V(StoreContextSlot)                          \
169
  V(StoreGlobalCell)                           \
170
  V(StoreGlobalGeneric)                        \
171
  V(StoreKeyed)                                \
172
  V(StoreKeyedGeneric)                         \
173
  V(StoreNamedField)                           \
174
  V(StoreNamedGeneric)                         \
175
  V(StringAdd)                                 \
176
  V(StringCharCodeAt)                          \
177
  V(StringCharFromCode)                        \
178
  V(StringCompareAndBranch)                    \
179
  V(Sub)                                       \
180
  V(ThisFunction)                              \
181
  V(Throw)                                     \
182
  V(ToFastProperties)                          \
183
  V(TransitionElementsKind)                    \
184
  V(TrapAllocationMemento)                     \
185
  V(Typeof)                                    \
186
  V(TypeofIsAndBranch)                         \
187
  V(UnaryMathOperation)                        \
188
  V(UnknownOSRValue)                           \
189
  V(UseConst)                                  \
190
  V(ValueOf)                                   \
191
  V(WrapReceiver)
192

    
193
#define GVN_TRACKED_FLAG_LIST(V)               \
194
  V(Maps)                                      \
195
  V(NewSpacePromotion)
196

    
197
#define GVN_UNTRACKED_FLAG_LIST(V)             \
198
  V(ArrayElements)                             \
199
  V(ArrayLengths)                              \
200
  V(StringLengths)                             \
201
  V(BackingStoreFields)                        \
202
  V(Calls)                                     \
203
  V(ContextSlots)                              \
204
  V(DoubleArrayElements)                       \
205
  V(DoubleFields)                              \
206
  V(ElementsKind)                              \
207
  V(ElementsPointer)                           \
208
  V(GlobalVars)                                \
209
  V(InobjectFields)                            \
210
  V(OsrEntries)                                \
211
  V(ExternalMemory)
212

    
213

    
214
#define DECLARE_ABSTRACT_INSTRUCTION(type)                              \
215
  virtual bool Is##type() const V8_FINAL V8_OVERRIDE { return true; }   \
216
  static H##type* cast(HValue* value) {                                 \
217
    ASSERT(value->Is##type());                                          \
218
    return reinterpret_cast<H##type*>(value);                           \
219
  }
220

    
221

    
222
#define DECLARE_CONCRETE_INSTRUCTION(type)              \
223
  virtual LInstruction* CompileToLithium(               \
224
     LChunkBuilder* builder) V8_FINAL V8_OVERRIDE;      \
225
  static H##type* cast(HValue* value) {                 \
226
    ASSERT(value->Is##type());                          \
227
    return reinterpret_cast<H##type*>(value);           \
228
  }                                                     \
229
  virtual Opcode opcode() const V8_FINAL V8_OVERRIDE {  \
230
    return HValue::k##type;                             \
231
  }
232

    
233

    
234
class Range V8_FINAL : public ZoneObject {
235
 public:
236
  Range()
237
      : lower_(kMinInt),
238
        upper_(kMaxInt),
239
        next_(NULL),
240
        can_be_minus_zero_(false) { }
241

    
242
  Range(int32_t lower, int32_t upper)
243
      : lower_(lower),
244
        upper_(upper),
245
        next_(NULL),
246
        can_be_minus_zero_(false) { }
247

    
248
  int32_t upper() const { return upper_; }
249
  int32_t lower() const { return lower_; }
250
  Range* next() const { return next_; }
251
  Range* CopyClearLower(Zone* zone) const {
252
    return new(zone) Range(kMinInt, upper_);
253
  }
254
  Range* CopyClearUpper(Zone* zone) const {
255
    return new(zone) Range(lower_, kMaxInt);
256
  }
257
  Range* Copy(Zone* zone) const {
258
    Range* result = new(zone) Range(lower_, upper_);
259
    result->set_can_be_minus_zero(CanBeMinusZero());
260
    return result;
261
  }
262
  int32_t Mask() const;
263
  void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
264
  bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
265
  bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
266
  bool CanBeNegative() const { return lower_ < 0; }
267
  bool CanBePositive() const { return upper_ > 0; }
268
  bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
269
  bool IsMostGeneric() const {
270
    return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
271
  }
272
  bool IsInSmiRange() const {
273
    return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
274
  }
275
  void ClampToSmi() {
276
    lower_ = Max(lower_, Smi::kMinValue);
277
    upper_ = Min(upper_, Smi::kMaxValue);
278
  }
279
  void KeepOrder();
280
#ifdef DEBUG
281
  void Verify() const;
282
#endif
283

    
284
  void StackUpon(Range* other) {
285
    Intersect(other);
286
    next_ = other;
287
  }
288

    
289
  void Intersect(Range* other);
290
  void Union(Range* other);
291
  void CombinedMax(Range* other);
292
  void CombinedMin(Range* other);
293

    
294
  void AddConstant(int32_t value);
295
  void Sar(int32_t value);
296
  void Shl(int32_t value);
297
  bool AddAndCheckOverflow(const Representation& r, Range* other);
298
  bool SubAndCheckOverflow(const Representation& r, Range* other);
299
  bool MulAndCheckOverflow(const Representation& r, Range* other);
300

    
301
 private:
302
  int32_t lower_;
303
  int32_t upper_;
304
  Range* next_;
305
  bool can_be_minus_zero_;
306
};
307

    
308

    
309
class HType V8_FINAL {
310
 public:
311
  static HType None() { return HType(kNone); }
312
  static HType Tagged() { return HType(kTagged); }
313
  static HType TaggedPrimitive() { return HType(kTaggedPrimitive); }
314
  static HType TaggedNumber() { return HType(kTaggedNumber); }
315
  static HType Smi() { return HType(kSmi); }
316
  static HType HeapNumber() { return HType(kHeapNumber); }
317
  static HType String() { return HType(kString); }
318
  static HType Boolean() { return HType(kBoolean); }
319
  static HType NonPrimitive() { return HType(kNonPrimitive); }
320
  static HType JSArray() { return HType(kJSArray); }
321
  static HType JSObject() { return HType(kJSObject); }
322

    
323
  // Return the weakest (least precise) common type.
324
  HType Combine(HType other) {
325
    return HType(static_cast<Type>(type_ & other.type_));
326
  }
327

    
328
  bool Equals(const HType& other) const {
329
    return type_ == other.type_;
330
  }
331

    
332
  bool IsSubtypeOf(const HType& other) {
333
    return Combine(other).Equals(other);
334
  }
335

    
336
  bool IsTaggedPrimitive() const {
337
    return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
338
  }
339

    
340
  bool IsTaggedNumber() const {
341
    return ((type_ & kTaggedNumber) == kTaggedNumber);
342
  }
343

    
344
  bool IsSmi() const {
345
    return ((type_ & kSmi) == kSmi);
346
  }
347

    
348
  bool IsHeapNumber() const {
349
    return ((type_ & kHeapNumber) == kHeapNumber);
350
  }
351

    
352
  bool IsString() const {
353
    return ((type_ & kString) == kString);
354
  }
355

    
356
  bool IsNonString() const {
357
    return IsTaggedPrimitive() || IsSmi() || IsHeapNumber() ||
358
        IsBoolean() || IsJSArray();
359
  }
360

    
361
  bool IsBoolean() const {
362
    return ((type_ & kBoolean) == kBoolean);
363
  }
364

    
365
  bool IsNonPrimitive() const {
366
    return ((type_ & kNonPrimitive) == kNonPrimitive);
367
  }
368

    
369
  bool IsJSArray() const {
370
    return ((type_ & kJSArray) == kJSArray);
371
  }
372

    
373
  bool IsJSObject() const {
374
    return ((type_ & kJSObject) == kJSObject);
375
  }
376

    
377
  bool IsHeapObject() const {
378
    return IsHeapNumber() || IsString() || IsBoolean() || IsNonPrimitive();
379
  }
380

    
381
  bool ToStringOrToNumberCanBeObserved(Representation representation) {
382
    switch (type_) {
383
      case kTaggedPrimitive:  // fallthru
384
      case kTaggedNumber:     // fallthru
385
      case kSmi:              // fallthru
386
      case kHeapNumber:       // fallthru
387
      case kString:           // fallthru
388
      case kBoolean:
389
        return false;
390
      case kJSArray:          // fallthru
391
      case kJSObject:
392
        return true;
393
      case kTagged:
394
        break;
395
    }
396
    return !representation.IsSmiOrInteger32() && !representation.IsDouble();
397
  }
398

    
399
  static HType TypeFromValue(Handle<Object> value);
400

    
401
  const char* ToString();
402

    
403
 private:
404
  enum Type {
405
    kNone = 0x0,             // 0000 0000 0000 0000
406
    kTagged = 0x1,           // 0000 0000 0000 0001
407
    kTaggedPrimitive = 0x5,  // 0000 0000 0000 0101
408
    kTaggedNumber = 0xd,     // 0000 0000 0000 1101
409
    kSmi = 0x1d,             // 0000 0000 0001 1101
410
    kHeapNumber = 0x2d,      // 0000 0000 0010 1101
411
    kString = 0x45,          // 0000 0000 0100 0101
412
    kBoolean = 0x85,         // 0000 0000 1000 0101
413
    kNonPrimitive = 0x101,   // 0000 0001 0000 0001
414
    kJSObject = 0x301,       // 0000 0011 0000 0001
415
    kJSArray = 0x701         // 0000 0111 0000 0001
416
  };
417

    
418
  // Make sure type fits in int16.
419
  STATIC_ASSERT(kJSArray < (1 << (2 * kBitsPerByte)));
420

    
421
  explicit HType(Type t) : type_(t) { }
422

    
423
  int16_t type_;
424
};
425

    
426

    
427
class HUseListNode: public ZoneObject {
428
 public:
429
  HUseListNode(HValue* value, int index, HUseListNode* tail)
430
      : tail_(tail), value_(value), index_(index) {
431
  }
432

    
433
  HUseListNode* tail();
434
  HValue* value() const { return value_; }
435
  int index() const { return index_; }
436

    
437
  void set_tail(HUseListNode* list) { tail_ = list; }
438

    
439
#ifdef DEBUG
440
  void Zap() {
441
    tail_ = reinterpret_cast<HUseListNode*>(1);
442
    value_ = NULL;
443
    index_ = -1;
444
  }
445
#endif
446

    
447
 private:
448
  HUseListNode* tail_;
449
  HValue* value_;
450
  int index_;
451
};
452

    
453

    
454
// We reuse use list nodes behind the scenes as uses are added and deleted.
455
// This class is the safe way to iterate uses while deleting them.
456
class HUseIterator V8_FINAL BASE_EMBEDDED {
457
 public:
458
  bool Done() { return current_ == NULL; }
459
  void Advance();
460

    
461
  HValue* value() {
462
    ASSERT(!Done());
463
    return value_;
464
  }
465

    
466
  int index() {
467
    ASSERT(!Done());
468
    return index_;
469
  }
470

    
471
 private:
472
  explicit HUseIterator(HUseListNode* head);
473

    
474
  HUseListNode* current_;
475
  HUseListNode* next_;
476
  HValue* value_;
477
  int index_;
478

    
479
  friend class HValue;
480
};
481

    
482

    
483
// There must be one corresponding kDepends flag for every kChanges flag and
484
// the order of the kChanges flags must be exactly the same as of the kDepends
485
// flags. All tracked flags should appear before untracked ones.
486
enum GVNFlag {
487
  // Declare global value numbering flags.
488
#define DECLARE_FLAG(type) kChanges##type, kDependsOn##type,
489
  GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
490
  GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
491
#undef DECLARE_FLAG
492
  kAfterLastFlag,
493
  kLastFlag = kAfterLastFlag - 1,
494
#define COUNT_FLAG(type) + 1
495
  kNumberOfTrackedSideEffects = 0 GVN_TRACKED_FLAG_LIST(COUNT_FLAG)
496
#undef COUNT_FLAG
497
};
498

    
499

    
500
class DecompositionResult V8_FINAL BASE_EMBEDDED {
501
 public:
502
  DecompositionResult() : base_(NULL), offset_(0), scale_(0) {}
503

    
504
  HValue* base() { return base_; }
505
  int offset() { return offset_; }
506
  int scale() { return scale_; }
507

    
508
  bool Apply(HValue* other_base, int other_offset, int other_scale = 0) {
509
    if (base_ == NULL) {
510
      base_ = other_base;
511
      offset_ = other_offset;
512
      scale_ = other_scale;
513
      return true;
514
    } else {
515
      if (scale_ == 0) {
516
        base_ = other_base;
517
        offset_ += other_offset;
518
        scale_ = other_scale;
519
        return true;
520
      } else {
521
        return false;
522
      }
523
    }
524
  }
525

    
526
  void SwapValues(HValue** other_base, int* other_offset, int* other_scale) {
527
    swap(&base_, other_base);
528
    swap(&offset_, other_offset);
529
    swap(&scale_, other_scale);
530
  }
531

    
532
 private:
533
  template <class T> void swap(T* a, T* b) {
534
    T c(*a);
535
    *a = *b;
536
    *b = c;
537
  }
538

    
539
  HValue* base_;
540
  int offset_;
541
  int scale_;
542
};
543

    
544

    
545
typedef EnumSet<GVNFlag> GVNFlagSet;
546

    
547

    
548
class HValue : public ZoneObject {
549
 public:
550
  static const int kNoNumber = -1;
551

    
552
  enum Flag {
553
    kFlexibleRepresentation,
554
    kCannotBeTagged,
555
    // Participate in Global Value Numbering, i.e. elimination of
556
    // unnecessary recomputations. If an instruction sets this flag, it must
557
    // implement DataEquals(), which will be used to determine if other
558
    // occurrences of the instruction are indeed the same.
559
    kUseGVN,
560
    // Track instructions that are dominating side effects. If an instruction
561
    // sets this flag, it must implement HandleSideEffectDominator() and should
562
    // indicate which side effects to track by setting GVN flags.
563
    kTrackSideEffectDominators,
564
    kCanOverflow,
565
    kBailoutOnMinusZero,
566
    kCanBeDivByZero,
567
    kAllowUndefinedAsNaN,
568
    kIsArguments,
569
    kTruncatingToInt32,
570
    kAllUsesTruncatingToInt32,
571
    kTruncatingToSmi,
572
    kAllUsesTruncatingToSmi,
573
    // Set after an instruction is killed.
574
    kIsDead,
575
    // Instructions that are allowed to produce full range unsigned integer
576
    // values are marked with kUint32 flag. If arithmetic shift or a load from
577
    // EXTERNAL_UNSIGNED_INT_ELEMENTS array is not marked with this flag
578
    // it will deoptimize if result does not fit into signed integer range.
579
    // HGraph::ComputeSafeUint32Operations is responsible for setting this
580
    // flag.
581
    kUint32,
582
    kHasNoObservableSideEffects,
583
    // Indicates the instruction is live during dead code elimination.
584
    kIsLive,
585

    
586
    // HEnvironmentMarkers are deleted before dead code
587
    // elimination takes place, so they can repurpose the kIsLive flag:
588
    kEndsLiveRange = kIsLive,
589

    
590
    // TODO(everyone): Don't forget to update this!
591
    kLastFlag = kIsLive
592
  };
593

    
594
  STATIC_ASSERT(kLastFlag < kBitsPerInt);
595

    
596
  static const int kChangesToDependsFlagsLeftShift = 1;
597

    
598
  static GVNFlag ChangesFlagFromInt(int x) {
599
    return static_cast<GVNFlag>(x * 2);
600
  }
601
  static GVNFlag DependsOnFlagFromInt(int x) {
602
    return static_cast<GVNFlag>(x * 2 + 1);
603
  }
604
  static GVNFlagSet ConvertChangesToDependsFlags(GVNFlagSet flags) {
605
    return GVNFlagSet(flags.ToIntegral() << kChangesToDependsFlagsLeftShift);
606
  }
607

    
608
  static HValue* cast(HValue* value) { return value; }
609

    
610
  enum Opcode {
611
    // Declare a unique enum value for each hydrogen instruction.
612
  #define DECLARE_OPCODE(type) k##type,
613
    HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
614
    kPhi
615
  #undef DECLARE_OPCODE
616
  };
617
  virtual Opcode opcode() const = 0;
618

    
619
  // Declare a non-virtual predicates for each concrete HInstruction or HValue.
620
  #define DECLARE_PREDICATE(type) \
621
    bool Is##type() const { return opcode() == k##type; }
622
    HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
623
  #undef DECLARE_PREDICATE
624
    bool IsPhi() const { return opcode() == kPhi; }
625

    
626
  // Declare virtual predicates for abstract HInstruction or HValue
627
  #define DECLARE_PREDICATE(type) \
628
    virtual bool Is##type() const { return false; }
629
    HYDROGEN_ABSTRACT_INSTRUCTION_LIST(DECLARE_PREDICATE)
630
  #undef DECLARE_PREDICATE
631

    
632
  HValue(HType type = HType::Tagged())
633
      : block_(NULL),
634
        id_(kNoNumber),
635
        type_(type),
636
        use_list_(NULL),
637
        range_(NULL),
638
        flags_(0) {}
639
  virtual ~HValue() {}
640

    
641
  virtual int position() const { return RelocInfo::kNoPosition; }
642

    
643
  HBasicBlock* block() const { return block_; }
644
  void SetBlock(HBasicBlock* block);
645
  int LoopWeight() const;
646

    
647
  // Note: Never call this method for an unlinked value.
648
  Isolate* isolate() const;
649

    
650
  int id() const { return id_; }
651
  void set_id(int id) { id_ = id; }
652

    
653
  HUseIterator uses() const { return HUseIterator(use_list_); }
654

    
655
  virtual bool EmitAtUses() { return false; }
656

    
657
  Representation representation() const { return representation_; }
658
  void ChangeRepresentation(Representation r) {
659
    ASSERT(CheckFlag(kFlexibleRepresentation));
660
    ASSERT(!CheckFlag(kCannotBeTagged) || !r.IsTagged());
661
    RepresentationChanged(r);
662
    representation_ = r;
663
    if (r.IsTagged()) {
664
      // Tagged is the bottom of the lattice, don't go any further.
665
      ClearFlag(kFlexibleRepresentation);
666
    }
667
  }
668
  virtual void AssumeRepresentation(Representation r);
669

    
670
  virtual Representation KnownOptimalRepresentation() {
671
    Representation r = representation();
672
    if (r.IsTagged()) {
673
      HType t = type();
674
      if (t.IsSmi()) return Representation::Smi();
675
      if (t.IsHeapNumber()) return Representation::Double();
676
      if (t.IsHeapObject()) return r;
677
      return Representation::None();
678
    }
679
    return r;
680
  }
681

    
682
  HType type() const { return type_; }
683
  void set_type(HType new_type) {
684
    ASSERT(new_type.IsSubtypeOf(type_));
685
    type_ = new_type;
686
  }
687

    
688
  bool IsHeapObject() {
689
    return representation_.IsHeapObject() || type_.IsHeapObject();
690
  }
691

    
692
  // An operation needs to override this function iff:
693
  //   1) it can produce an int32 output.
694
  //   2) the true value of its output can potentially be minus zero.
695
  // The implementation must set a flag so that it bails out in the case where
696
  // it would otherwise output what should be a minus zero as an int32 zero.
697
  // If the operation also exists in a form that takes int32 and outputs int32
698
  // then the operation should return its input value so that we can propagate
699
  // back.  There are three operations that need to propagate back to more than
700
  // one input.  They are phi and binary div and mul.  They always return NULL
701
  // and expect the caller to take care of things.
702
  virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) {
703
    visited->Add(id());
704
    return NULL;
705
  }
706

    
707
  // There are HInstructions that do not really change a value, they
708
  // only add pieces of information to it (like bounds checks, map checks,
709
  // smi checks...).
710
  // We call these instructions "informative definitions", or "iDef".
711
  // One of the iDef operands is special because it is the value that is
712
  // "transferred" to the output, we call it the "redefined operand".
713
  // If an HValue is an iDef it must override RedefinedOperandIndex() so that
714
  // it does not return kNoRedefinedOperand;
715
  static const int kNoRedefinedOperand = -1;
716
  virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; }
717
  bool IsInformativeDefinition() {
718
    return RedefinedOperandIndex() != kNoRedefinedOperand;
719
  }
720
  HValue* RedefinedOperand() {
721
    int index = RedefinedOperandIndex();
722
    return index == kNoRedefinedOperand ? NULL : OperandAt(index);
723
  }
724

    
725
  bool CanReplaceWithDummyUses();
726

    
727
  virtual int argument_delta() const { return 0; }
728

    
729
  // A purely informative definition is an idef that will not emit code and
730
  // should therefore be removed from the graph in the RestoreActualValues
731
  // phase (so that live ranges will be shorter).
732
  virtual bool IsPurelyInformativeDefinition() { return false; }
733

    
734
  // This method must always return the original HValue SSA definition,
735
  // regardless of any chain of iDefs of this value.
736
  HValue* ActualValue() {
737
    HValue* value = this;
738
    int index;
739
    while ((index = value->RedefinedOperandIndex()) != kNoRedefinedOperand) {
740
      value = value->OperandAt(index);
741
    }
742
    return value;
743
  }
744

    
745
  bool IsInteger32Constant();
746
  int32_t GetInteger32Constant();
747
  bool EqualsInteger32Constant(int32_t value);
748

    
749
  bool IsDefinedAfter(HBasicBlock* other) const;
750

    
751
  // Operands.
752
  virtual int OperandCount() = 0;
753
  virtual HValue* OperandAt(int index) const = 0;
754
  void SetOperandAt(int index, HValue* value);
755

    
756
  void DeleteAndReplaceWith(HValue* other);
757
  void ReplaceAllUsesWith(HValue* other);
758
  bool HasNoUses() const { return use_list_ == NULL; }
759
  bool HasMultipleUses() const {
760
    return use_list_ != NULL && use_list_->tail() != NULL;
761
  }
762
  int UseCount() const;
763

    
764
  // Mark this HValue as dead and to be removed from other HValues' use lists.
765
  void Kill();
766

    
767
  int flags() const { return flags_; }
768
  void SetFlag(Flag f) { flags_ |= (1 << f); }
769
  void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
770
  bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
771
  void CopyFlag(Flag f, HValue* other) {
772
    if (other->CheckFlag(f)) SetFlag(f);
773
  }
774

    
775
  // Returns true if the flag specified is set for all uses, false otherwise.
776
  bool CheckUsesForFlag(Flag f) const;
777
  // Same as before and the first one without the flag is returned in value.
778
  bool CheckUsesForFlag(Flag f, HValue** value) const;
779
  // Returns true if the flag specified is set for all uses, and this set
780
  // of uses is non-empty.
781
  bool HasAtLeastOneUseWithFlagAndNoneWithout(Flag f) const;
782

    
783
  GVNFlagSet gvn_flags() const { return gvn_flags_; }
784
  void SetGVNFlag(GVNFlag f) { gvn_flags_.Add(f); }
785
  void ClearGVNFlag(GVNFlag f) { gvn_flags_.Remove(f); }
786
  bool CheckGVNFlag(GVNFlag f) const { return gvn_flags_.Contains(f); }
787
  void SetAllSideEffects() { gvn_flags_.Add(AllSideEffectsFlagSet()); }
788
  void ClearAllSideEffects() {
789
    gvn_flags_.Remove(AllSideEffectsFlagSet());
790
  }
791
  bool HasSideEffects() const {
792
    return gvn_flags_.ContainsAnyOf(AllSideEffectsFlagSet());
793
  }
794
  bool HasObservableSideEffects() const {
795
    return !CheckFlag(kHasNoObservableSideEffects) &&
796
        gvn_flags_.ContainsAnyOf(AllObservableSideEffectsFlagSet());
797
  }
798

    
799
  GVNFlagSet DependsOnFlags() const {
800
    GVNFlagSet result = gvn_flags_;
801
    result.Intersect(AllDependsOnFlagSet());
802
    return result;
803
  }
804

    
805
  GVNFlagSet SideEffectFlags() const {
806
    GVNFlagSet result = gvn_flags_;
807
    result.Intersect(AllSideEffectsFlagSet());
808
    return result;
809
  }
810

    
811
  GVNFlagSet ChangesFlags() const {
812
    GVNFlagSet result = gvn_flags_;
813
    result.Intersect(AllChangesFlagSet());
814
    return result;
815
  }
816

    
817
  GVNFlagSet ObservableChangesFlags() const {
818
    GVNFlagSet result = gvn_flags_;
819
    result.Intersect(AllChangesFlagSet());
820
    result.Intersect(AllObservableSideEffectsFlagSet());
821
    return result;
822
  }
823

    
824
  Range* range() const { return range_; }
825
  // TODO(svenpanne) We should really use the null object pattern here.
826
  bool HasRange() const { return range_ != NULL; }
827
  bool CanBeNegative() const { return !HasRange() || range()->CanBeNegative(); }
828
  bool CanBeZero() const { return !HasRange() || range()->CanBeZero(); }
829
  bool RangeCanInclude(int value) const {
830
    return !HasRange() || range()->Includes(value);
831
  }
832
  void AddNewRange(Range* r, Zone* zone);
833
  void RemoveLastAddedRange();
834
  void ComputeInitialRange(Zone* zone);
835

    
836
  // Escape analysis helpers.
837
  virtual bool HasEscapingOperandAt(int index) { return true; }
838
  virtual bool HasOutOfBoundsAccess(int size) { return false; }
839

    
840
  // Representation helpers.
841
  virtual Representation observed_input_representation(int index) {
842
    return Representation::None();
843
  }
844
  virtual Representation RequiredInputRepresentation(int index) = 0;
845
  virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
846

    
847
  // This gives the instruction an opportunity to replace itself with an
848
  // instruction that does the same in some better way.  To replace an
849
  // instruction with a new one, first add the new instruction to the graph,
850
  // then return it.  Return NULL to have the instruction deleted.
851
  virtual HValue* Canonicalize() { return this; }
852

    
853
  bool Equals(HValue* other);
854
  virtual intptr_t Hashcode();
855

    
856
  // Compute unique ids upfront that is safe wrt GC and concurrent compilation.
857
  virtual void FinalizeUniqueness() { }
858

    
859
  // Printing support.
860
  virtual void PrintTo(StringStream* stream) = 0;
861
  void PrintNameTo(StringStream* stream);
862
  void PrintTypeTo(StringStream* stream);
863
  void PrintRangeTo(StringStream* stream);
864
  void PrintChangesTo(StringStream* stream);
865

    
866
  const char* Mnemonic() const;
867

    
868
  // Type information helpers.
869
  bool HasMonomorphicJSObjectType();
870

    
871
  // TODO(mstarzinger): For now instructions can override this function to
872
  // specify statically known types, once HType can convey more information
873
  // it should be based on the HType.
874
  virtual Handle<Map> GetMonomorphicJSObjectMap() { return Handle<Map>(); }
875

    
876
  // Updated the inferred type of this instruction and returns true if
877
  // it has changed.
878
  bool UpdateInferredType();
879

    
880
  virtual HType CalculateInferredType();
881

    
882
  // This function must be overridden for instructions which have the
883
  // kTrackSideEffectDominators flag set, to track instructions that are
884
  // dominating side effects.
885
  virtual void HandleSideEffectDominator(GVNFlag side_effect,
886
                                         HValue* dominator) {
887
    UNREACHABLE();
888
  }
889

    
890
  // Check if this instruction has some reason that prevents elimination.
891
  bool CannotBeEliminated() const {
892
    return HasObservableSideEffects() || !IsDeletable();
893
  }
894

    
895
#ifdef DEBUG
896
  virtual void Verify() = 0;
897
#endif
898

    
899
  virtual bool TryDecompose(DecompositionResult* decomposition) {
900
    if (RedefinedOperand() != NULL) {
901
      return RedefinedOperand()->TryDecompose(decomposition);
902
    } else {
903
      return false;
904
    }
905
  }
906

    
907
  // Returns true conservatively if the program might be able to observe a
908
  // ToString() operation on this value.
909
  bool ToStringCanBeObserved() const {
910
    return type().ToStringOrToNumberCanBeObserved(representation());
911
  }
912

    
913
  // Returns true conservatively if the program might be able to observe a
914
  // ToNumber() operation on this value.
915
  bool ToNumberCanBeObserved() const {
916
    return type().ToStringOrToNumberCanBeObserved(representation());
917
  }
918

    
919
  MinusZeroMode GetMinusZeroMode() {
920
    return CheckFlag(kBailoutOnMinusZero)
921
        ? FAIL_ON_MINUS_ZERO : TREAT_MINUS_ZERO_AS_ZERO;
922
  }
923

    
924
 protected:
925
  // This function must be overridden for instructions with flag kUseGVN, to
926
  // compare the non-Operand parts of the instruction.
927
  virtual bool DataEquals(HValue* other) {
928
    UNREACHABLE();
929
    return false;
930
  }
931

    
932
  virtual Representation RepresentationFromInputs() {
933
    return representation();
934
  }
935
  Representation RepresentationFromUses();
936
  Representation RepresentationFromUseRequirements();
937
  bool HasNonSmiUse();
938
  virtual void UpdateRepresentation(Representation new_rep,
939
                                    HInferRepresentationPhase* h_infer,
940
                                    const char* reason);
941
  void AddDependantsToWorklist(HInferRepresentationPhase* h_infer);
942

    
943
  virtual void RepresentationChanged(Representation to) { }
944

    
945
  virtual Range* InferRange(Zone* zone);
946
  virtual void DeleteFromGraph() = 0;
947
  virtual void InternalSetOperandAt(int index, HValue* value) = 0;
948
  void clear_block() {
949
    ASSERT(block_ != NULL);
950
    block_ = NULL;
951
  }
952

    
953
  void set_representation(Representation r) {
954
    ASSERT(representation_.IsNone() && !r.IsNone());
955
    representation_ = r;
956
  }
957

    
958
  static GVNFlagSet AllDependsOnFlagSet() {
959
    GVNFlagSet result;
960
    // Create changes mask.
961
#define ADD_FLAG(type) result.Add(kDependsOn##type);
962
  GVN_TRACKED_FLAG_LIST(ADD_FLAG)
963
  GVN_UNTRACKED_FLAG_LIST(ADD_FLAG)
964
#undef ADD_FLAG
965
    return result;
966
  }
967

    
968
  static GVNFlagSet AllChangesFlagSet() {
969
    GVNFlagSet result;
970
    // Create changes mask.
971
#define ADD_FLAG(type) result.Add(kChanges##type);
972
  GVN_TRACKED_FLAG_LIST(ADD_FLAG)
973
  GVN_UNTRACKED_FLAG_LIST(ADD_FLAG)
974
#undef ADD_FLAG
975
    return result;
976
  }
977

    
978
  // A flag mask to mark an instruction as having arbitrary side effects.
979
  static GVNFlagSet AllSideEffectsFlagSet() {
980
    GVNFlagSet result = AllChangesFlagSet();
981
    result.Remove(kChangesOsrEntries);
982
    return result;
983
  }
984

    
985
  // A flag mask of all side effects that can make observable changes in
986
  // an executing program (i.e. are not safe to repeat, move or remove);
987
  static GVNFlagSet AllObservableSideEffectsFlagSet() {
988
    GVNFlagSet result = AllChangesFlagSet();
989
    result.Remove(kChangesNewSpacePromotion);
990
    result.Remove(kChangesElementsKind);
991
    result.Remove(kChangesElementsPointer);
992
    result.Remove(kChangesMaps);
993
    return result;
994
  }
995

    
996
  // Remove the matching use from the use list if present.  Returns the
997
  // removed list node or NULL.
998
  HUseListNode* RemoveUse(HValue* value, int index);
999

    
1000
  void RegisterUse(int index, HValue* new_value);
1001

    
1002
  HBasicBlock* block_;
1003

    
1004
  // The id of this instruction in the hydrogen graph, assigned when first
1005
  // added to the graph. Reflects creation order.
1006
  int id_;
1007

    
1008
  Representation representation_;
1009
  HType type_;
1010
  HUseListNode* use_list_;
1011
  Range* range_;
1012
  int flags_;
1013
  GVNFlagSet gvn_flags_;
1014

    
1015
 private:
1016
  virtual bool IsDeletable() const { return false; }
1017

    
1018
  DISALLOW_COPY_AND_ASSIGN(HValue);
1019
};
1020

    
1021

    
1022
#define DECLARE_INSTRUCTION_FACTORY_P0(I)                                      \
1023
  static I* New(Zone* zone, HValue* context) {                                 \
1024
    return new(zone) I();                                                      \
1025
}
1026

    
1027
#define DECLARE_INSTRUCTION_FACTORY_P1(I, P1)                                  \
1028
  static I* New(Zone* zone, HValue* context, P1 p1) {                          \
1029
    return new(zone) I(p1);                                                    \
1030
  }
1031

    
1032
#define DECLARE_INSTRUCTION_FACTORY_P2(I, P1, P2)                              \
1033
  static I* New(Zone* zone, HValue* context, P1 p1, P2 p2) {                   \
1034
    return new(zone) I(p1, p2);                                                \
1035
  }
1036

    
1037
#define DECLARE_INSTRUCTION_FACTORY_P3(I, P1, P2, P3)                          \
1038
  static I* New(Zone* zone, HValue* context, P1 p1, P2 p2, P3 p3) {            \
1039
    return new(zone) I(p1, p2, p3);                                            \
1040
  }
1041

    
1042
#define DECLARE_INSTRUCTION_FACTORY_P4(I, P1, P2, P3, P4)                      \
1043
  static I* New(Zone* zone,                                                    \
1044
                HValue* context,                                               \
1045
                P1 p1,                                                         \
1046
                P2 p2,                                                         \
1047
                P3 p3,                                                         \
1048
                P4 p4) {                                                       \
1049
    return new(zone) I(p1, p2, p3, p4);                                        \
1050
  }
1051

    
1052
#define DECLARE_INSTRUCTION_FACTORY_P5(I, P1, P2, P3, P4, P5)                  \
1053
  static I* New(Zone* zone,                                                    \
1054
                HValue* context,                                               \
1055
                P1 p1,                                                         \
1056
                P2 p2,                                                         \
1057
                P3 p3,                                                         \
1058
                P4 p4,                                                         \
1059
                P5 p5) {                                                       \
1060
    return new(zone) I(p1, p2, p3, p4, p5);                                    \
1061
  }
1062

    
1063
#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P0(I)                         \
1064
  static I* New(Zone* zone, HValue* context) {                                 \
1065
    return new(zone) I(context);                                               \
1066
  }
1067

    
1068
#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(I, P1)                     \
1069
  static I* New(Zone* zone, HValue* context, P1 p1) {                          \
1070
    return new(zone) I(context, p1);                                           \
1071
  }
1072

    
1073
#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(I, P1, P2)                 \
1074
  static I* New(Zone* zone, HValue* context, P1 p1, P2 p2) {                   \
1075
    return new(zone) I(context, p1, p2);                                       \
1076
  }
1077

    
1078
#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(I, P1, P2, P3)             \
1079
  static I* New(Zone* zone, HValue* context, P1 p1, P2 p2, P3 p3) {            \
1080
    return new(zone) I(context, p1, p2, p3);                                   \
1081
  }
1082

    
1083
#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(I, P1, P2, P3, P4)         \
1084
  static I* New(Zone* zone,                                                    \
1085
                HValue* context,                                               \
1086
                P1 p1,                                                         \
1087
                P2 p2,                                                         \
1088
                P3 p3,                                                         \
1089
                P4 p4) {                                                       \
1090
    return new(zone) I(context, p1, p2, p3, p4);                               \
1091
  }
1092

    
1093
#define DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(I, P1, P2, P3, P4, P5)     \
1094
  static I* New(Zone* zone,                                                    \
1095
                HValue* context,                                               \
1096
                P1 p1,                                                         \
1097
                P2 p2,                                                         \
1098
                P3 p3,                                                         \
1099
                P4 p4,                                                         \
1100
                P5 p5) {                                                       \
1101
    return new(zone) I(context, p1, p2, p3, p4, p5);                           \
1102
  }
1103

    
1104

    
1105
class HInstruction : public HValue {
1106
 public:
1107
  HInstruction* next() const { return next_; }
1108
  HInstruction* previous() const { return previous_; }
1109

    
1110
  virtual void PrintTo(StringStream* stream) V8_OVERRIDE;
1111
  virtual void PrintDataTo(StringStream* stream);
1112

    
1113
  bool IsLinked() const { return block() != NULL; }
1114
  void Unlink();
1115
  void InsertBefore(HInstruction* next);
1116
  void InsertAfter(HInstruction* previous);
1117

    
1118
  // The position is a write-once variable.
1119
  virtual int position() const V8_OVERRIDE { return position_; }
1120
  bool has_position() const { return position_ != RelocInfo::kNoPosition; }
1121
  void set_position(int position) {
1122
    ASSERT(!has_position());
1123
    ASSERT(position != RelocInfo::kNoPosition);
1124
    position_ = position;
1125
  }
1126

    
1127
  bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); }
1128

    
1129
  virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
1130

    
1131
#ifdef DEBUG
1132
  virtual void Verify() V8_OVERRIDE;
1133
#endif
1134

    
1135
  virtual bool IsCall() { return false; }
1136

    
1137
  DECLARE_ABSTRACT_INSTRUCTION(Instruction)
1138

    
1139
 protected:
1140
  HInstruction(HType type = HType::Tagged())
1141
      : HValue(type),
1142
        next_(NULL),
1143
        previous_(NULL),
1144
        position_(RelocInfo::kNoPosition) {
1145
    SetGVNFlag(kDependsOnOsrEntries);
1146
  }
1147

    
1148
  virtual void DeleteFromGraph() V8_OVERRIDE { Unlink(); }
1149

    
1150
 private:
1151
  void InitializeAsFirst(HBasicBlock* block) {
1152
    ASSERT(!IsLinked());
1153
    SetBlock(block);
1154
  }
1155

    
1156
  void PrintMnemonicTo(StringStream* stream);
1157

    
1158
  HInstruction* next_;
1159
  HInstruction* previous_;
1160
  int position_;
1161

    
1162
  friend class HBasicBlock;
1163
};
1164

    
1165

    
1166
template<int V>
1167
class HTemplateInstruction : public HInstruction {
1168
 public:
1169
  virtual int OperandCount() V8_FINAL V8_OVERRIDE { return V; }
1170
  virtual HValue* OperandAt(int i) const V8_FINAL V8_OVERRIDE {
1171
    return inputs_[i];
1172
  }
1173

    
1174
 protected:
1175
  HTemplateInstruction(HType type = HType::Tagged()) : HInstruction(type) {}
1176

    
1177
  virtual void InternalSetOperandAt(int i, HValue* value) V8_FINAL V8_OVERRIDE {
1178
    inputs_[i] = value;
1179
  }
1180

    
1181
 private:
1182
  EmbeddedContainer<HValue*, V> inputs_;
1183
};
1184

    
1185

    
1186
class HControlInstruction : public HInstruction {
1187
 public:
1188
  virtual HBasicBlock* SuccessorAt(int i) = 0;
1189
  virtual int SuccessorCount() = 0;
1190
  virtual void SetSuccessorAt(int i, HBasicBlock* block) = 0;
1191

    
1192
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1193

    
1194
  virtual bool KnownSuccessorBlock(HBasicBlock** block) {
1195
    *block = NULL;
1196
    return false;
1197
  }
1198

    
1199
  HBasicBlock* FirstSuccessor() {
1200
    return SuccessorCount() > 0 ? SuccessorAt(0) : NULL;
1201
  }
1202
  HBasicBlock* SecondSuccessor() {
1203
    return SuccessorCount() > 1 ? SuccessorAt(1) : NULL;
1204
  }
1205

    
1206
  void Not() {
1207
    HBasicBlock* swap = SuccessorAt(0);
1208
    SetSuccessorAt(0, SuccessorAt(1));
1209
    SetSuccessorAt(1, swap);
1210
  }
1211

    
1212
  DECLARE_ABSTRACT_INSTRUCTION(ControlInstruction)
1213
};
1214

    
1215

    
1216
class HSuccessorIterator V8_FINAL BASE_EMBEDDED {
1217
 public:
1218
  explicit HSuccessorIterator(HControlInstruction* instr)
1219
      : instr_(instr), current_(0) { }
1220

    
1221
  bool Done() { return current_ >= instr_->SuccessorCount(); }
1222
  HBasicBlock* Current() { return instr_->SuccessorAt(current_); }
1223
  void Advance() { current_++; }
1224

    
1225
 private:
1226
  HControlInstruction* instr_;
1227
  int current_;
1228
};
1229

    
1230

    
1231
template<int S, int V>
1232
class HTemplateControlInstruction : public HControlInstruction {
1233
 public:
1234
  int SuccessorCount() V8_OVERRIDE { return S; }
1235
  HBasicBlock* SuccessorAt(int i) V8_OVERRIDE { return successors_[i]; }
1236
  void SetSuccessorAt(int i, HBasicBlock* block) V8_OVERRIDE {
1237
    successors_[i] = block;
1238
  }
1239

    
1240
  int OperandCount() V8_OVERRIDE { return V; }
1241
  HValue* OperandAt(int i) const V8_OVERRIDE { return inputs_[i]; }
1242

    
1243

    
1244
 protected:
1245
  void InternalSetOperandAt(int i, HValue* value) V8_OVERRIDE {
1246
    inputs_[i] = value;
1247
  }
1248

    
1249
 private:
1250
  EmbeddedContainer<HBasicBlock*, S> successors_;
1251
  EmbeddedContainer<HValue*, V> inputs_;
1252
};
1253

    
1254

    
1255
class HBlockEntry V8_FINAL : public HTemplateInstruction<0> {
1256
 public:
1257
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1258
    return Representation::None();
1259
  }
1260

    
1261
  DECLARE_CONCRETE_INSTRUCTION(BlockEntry)
1262
};
1263

    
1264

    
1265
class HDummyUse V8_FINAL : public HTemplateInstruction<1> {
1266
 public:
1267
  explicit HDummyUse(HValue* value)
1268
      : HTemplateInstruction<1>(HType::Smi()) {
1269
    SetOperandAt(0, value);
1270
    // Pretend to be a Smi so that the HChange instructions inserted
1271
    // before any use generate as little code as possible.
1272
    set_representation(Representation::Tagged());
1273
  }
1274

    
1275
  HValue* value() { return OperandAt(0); }
1276

    
1277
  virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
1278
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1279
    return Representation::None();
1280
  }
1281

    
1282
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1283

    
1284
  DECLARE_CONCRETE_INSTRUCTION(DummyUse);
1285
};
1286

    
1287

    
1288
// Inserts an int3/stop break instruction for debugging purposes.
1289
class HDebugBreak V8_FINAL : public HTemplateInstruction<0> {
1290
 public:
1291
  DECLARE_INSTRUCTION_FACTORY_P0(HDebugBreak);
1292

    
1293
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1294
    return Representation::None();
1295
  }
1296

    
1297
  DECLARE_CONCRETE_INSTRUCTION(DebugBreak)
1298
};
1299

    
1300

    
1301
class HGoto V8_FINAL : public HTemplateControlInstruction<1, 0> {
1302
 public:
1303
  explicit HGoto(HBasicBlock* target) {
1304
    SetSuccessorAt(0, target);
1305
  }
1306

    
1307
  virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE {
1308
    *block = FirstSuccessor();
1309
    return true;
1310
  }
1311

    
1312
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1313
    return Representation::None();
1314
  }
1315

    
1316
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1317

    
1318
  DECLARE_CONCRETE_INSTRUCTION(Goto)
1319
};
1320

    
1321

    
1322
class HDeoptimize V8_FINAL : public HTemplateControlInstruction<1, 0> {
1323
 public:
1324
  static HInstruction* New(Zone* zone,
1325
                           HValue* context,
1326
                           const char* reason,
1327
                           Deoptimizer::BailoutType type,
1328
                           HBasicBlock* unreachable_continuation) {
1329
    return new(zone) HDeoptimize(reason, type, unreachable_continuation);
1330
  }
1331

    
1332
  virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE {
1333
    *block = NULL;
1334
    return true;
1335
  }
1336

    
1337
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1338
    return Representation::None();
1339
  }
1340

    
1341
  const char* reason() const { return reason_; }
1342
  Deoptimizer::BailoutType type() { return type_; }
1343

    
1344
  DECLARE_CONCRETE_INSTRUCTION(Deoptimize)
1345

    
1346
 private:
1347
  explicit HDeoptimize(const char* reason,
1348
                       Deoptimizer::BailoutType type,
1349
                       HBasicBlock* unreachable_continuation)
1350
      : reason_(reason), type_(type) {
1351
    SetSuccessorAt(0, unreachable_continuation);
1352
  }
1353

    
1354
  const char* reason_;
1355
  Deoptimizer::BailoutType type_;
1356
};
1357

    
1358

    
1359
class HUnaryControlInstruction : public HTemplateControlInstruction<2, 1> {
1360
 public:
1361
  HUnaryControlInstruction(HValue* value,
1362
                           HBasicBlock* true_target,
1363
                           HBasicBlock* false_target) {
1364
    SetOperandAt(0, value);
1365
    SetSuccessorAt(0, true_target);
1366
    SetSuccessorAt(1, false_target);
1367
  }
1368

    
1369
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1370

    
1371
  HValue* value() { return OperandAt(0); }
1372
};
1373

    
1374

    
1375
class HBranch V8_FINAL : public HUnaryControlInstruction {
1376
 public:
1377
  DECLARE_INSTRUCTION_FACTORY_P1(HBranch, HValue*);
1378
  DECLARE_INSTRUCTION_FACTORY_P2(HBranch, HValue*,
1379
                                 ToBooleanStub::Types);
1380
  DECLARE_INSTRUCTION_FACTORY_P4(HBranch, HValue*,
1381
                                 ToBooleanStub::Types,
1382
                                 HBasicBlock*, HBasicBlock*);
1383

    
1384
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1385
    return Representation::None();
1386
  }
1387
  virtual Representation observed_input_representation(int index) V8_OVERRIDE;
1388

    
1389
  virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
1390

    
1391
  ToBooleanStub::Types expected_input_types() const {
1392
    return expected_input_types_;
1393
  }
1394

    
1395
  DECLARE_CONCRETE_INSTRUCTION(Branch)
1396

    
1397
 private:
1398
  HBranch(HValue* value,
1399
          ToBooleanStub::Types expected_input_types = ToBooleanStub::Types(),
1400
          HBasicBlock* true_target = NULL,
1401
          HBasicBlock* false_target = NULL)
1402
      : HUnaryControlInstruction(value, true_target, false_target),
1403
        expected_input_types_(expected_input_types) {
1404
    SetFlag(kAllowUndefinedAsNaN);
1405
  }
1406

    
1407
  ToBooleanStub::Types expected_input_types_;
1408
};
1409

    
1410

    
1411
class HCompareMap V8_FINAL : public HUnaryControlInstruction {
1412
 public:
1413
  DECLARE_INSTRUCTION_FACTORY_P2(HCompareMap, HValue*, Handle<Map>);
1414
  DECLARE_INSTRUCTION_FACTORY_P4(HCompareMap, HValue*, Handle<Map>,
1415
                                 HBasicBlock*, HBasicBlock*);
1416

    
1417
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1418

    
1419
  Unique<Map> map() const { return map_; }
1420

    
1421
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1422
    return Representation::Tagged();
1423
  }
1424

    
1425
  DECLARE_CONCRETE_INSTRUCTION(CompareMap)
1426

    
1427
 protected:
1428
  virtual int RedefinedOperandIndex() { return 0; }
1429

    
1430
 private:
1431
  HCompareMap(HValue* value,
1432
              Handle<Map> map,
1433
              HBasicBlock* true_target = NULL,
1434
              HBasicBlock* false_target = NULL)
1435
      : HUnaryControlInstruction(value, true_target, false_target),
1436
        map_(Unique<Map>(map)) {
1437
    ASSERT(!map.is_null());
1438
  }
1439

    
1440
  Unique<Map> map_;
1441
};
1442

    
1443

    
1444
class HContext V8_FINAL : public HTemplateInstruction<0> {
1445
 public:
1446
  static HContext* New(Zone* zone) {
1447
    return new(zone) HContext();
1448
  }
1449

    
1450
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1451
    return Representation::None();
1452
  }
1453

    
1454
  DECLARE_CONCRETE_INSTRUCTION(Context)
1455

    
1456
 protected:
1457
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
1458

    
1459
 private:
1460
  HContext() {
1461
    set_representation(Representation::Tagged());
1462
    SetFlag(kUseGVN);
1463
  }
1464

    
1465
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
1466
};
1467

    
1468

    
1469
class HReturn V8_FINAL : public HTemplateControlInstruction<0, 3> {
1470
 public:
1471
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HReturn, HValue*, HValue*);
1472
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HReturn, HValue*);
1473

    
1474
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1475
    return Representation::Tagged();
1476
  }
1477

    
1478
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1479

    
1480
  HValue* value() { return OperandAt(0); }
1481
  HValue* context() { return OperandAt(1); }
1482
  HValue* parameter_count() { return OperandAt(2); }
1483

    
1484
  DECLARE_CONCRETE_INSTRUCTION(Return)
1485

    
1486
 private:
1487
  HReturn(HValue* context, HValue* value, HValue* parameter_count = 0) {
1488
    SetOperandAt(0, value);
1489
    SetOperandAt(1, context);
1490
    SetOperandAt(2, parameter_count);
1491
  }
1492
};
1493

    
1494

    
1495
class HAbnormalExit V8_FINAL : public HTemplateControlInstruction<0, 0> {
1496
 public:
1497
  DECLARE_INSTRUCTION_FACTORY_P0(HAbnormalExit);
1498

    
1499
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1500
    return Representation::None();
1501
  }
1502

    
1503
  DECLARE_CONCRETE_INSTRUCTION(AbnormalExit)
1504
 private:
1505
  HAbnormalExit() {}
1506
};
1507

    
1508

    
1509
class HUnaryOperation : public HTemplateInstruction<1> {
1510
 public:
1511
  HUnaryOperation(HValue* value, HType type = HType::Tagged())
1512
      : HTemplateInstruction<1>(type) {
1513
    SetOperandAt(0, value);
1514
  }
1515

    
1516
  static HUnaryOperation* cast(HValue* value) {
1517
    return reinterpret_cast<HUnaryOperation*>(value);
1518
  }
1519

    
1520
  HValue* value() const { return OperandAt(0); }
1521
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1522
};
1523

    
1524

    
1525
class HThrow V8_FINAL : public HTemplateInstruction<2> {
1526
 public:
1527
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HThrow, HValue*);
1528

    
1529
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1530
    return Representation::Tagged();
1531
  }
1532

    
1533
  HValue* context() { return OperandAt(0); }
1534
  HValue* value() { return OperandAt(1); }
1535

    
1536
  DECLARE_CONCRETE_INSTRUCTION(Throw)
1537

    
1538
 private:
1539
  HThrow(HValue* context, HValue* value) {
1540
    SetOperandAt(0, context);
1541
    SetOperandAt(1, value);
1542
    SetAllSideEffects();
1543
  }
1544
};
1545

    
1546

    
1547
class HUseConst V8_FINAL : public HUnaryOperation {
1548
 public:
1549
  DECLARE_INSTRUCTION_FACTORY_P1(HUseConst, HValue*);
1550

    
1551
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1552
    return Representation::None();
1553
  }
1554

    
1555
  DECLARE_CONCRETE_INSTRUCTION(UseConst)
1556

    
1557
 private:
1558
    explicit HUseConst(HValue* old_value) : HUnaryOperation(old_value) { }
1559
};
1560

    
1561

    
1562
class HForceRepresentation V8_FINAL : public HTemplateInstruction<1> {
1563
 public:
1564
  DECLARE_INSTRUCTION_FACTORY_P2(HForceRepresentation, HValue*, Representation);
1565

    
1566
  HValue* value() { return OperandAt(0); }
1567

    
1568
  virtual HValue* EnsureAndPropagateNotMinusZero(
1569
      BitVector* visited) V8_OVERRIDE;
1570

    
1571
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1572
    return representation();  // Same as the output representation.
1573
  }
1574

    
1575
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1576

    
1577
  DECLARE_CONCRETE_INSTRUCTION(ForceRepresentation)
1578

    
1579
 private:
1580
  HForceRepresentation(HValue* value, Representation required_representation) {
1581
    SetOperandAt(0, value);
1582
    set_representation(required_representation);
1583
  }
1584
};
1585

    
1586

    
1587
class HChange V8_FINAL : public HUnaryOperation {
1588
 public:
1589
  HChange(HValue* value,
1590
          Representation to,
1591
          bool is_truncating_to_smi,
1592
          bool is_truncating_to_int32)
1593
      : HUnaryOperation(value) {
1594
    ASSERT(!value->representation().IsNone());
1595
    ASSERT(!to.IsNone());
1596
    ASSERT(!value->representation().Equals(to));
1597
    set_representation(to);
1598
    SetFlag(kUseGVN);
1599
    if (is_truncating_to_smi) {
1600
      SetFlag(kTruncatingToSmi);
1601
      SetFlag(kTruncatingToInt32);
1602
    }
1603
    if (is_truncating_to_int32) SetFlag(kTruncatingToInt32);
1604
    if (value->representation().IsSmi() || value->type().IsSmi()) {
1605
      set_type(HType::Smi());
1606
    } else {
1607
      set_type(HType::TaggedNumber());
1608
      if (to.IsTagged()) SetGVNFlag(kChangesNewSpacePromotion);
1609
    }
1610
  }
1611

    
1612
  bool can_convert_undefined_to_nan() {
1613
    return CheckUsesForFlag(kAllowUndefinedAsNaN);
1614
  }
1615

    
1616
  virtual HValue* EnsureAndPropagateNotMinusZero(
1617
      BitVector* visited) V8_OVERRIDE;
1618
  virtual HType CalculateInferredType() V8_OVERRIDE;
1619
  virtual HValue* Canonicalize() V8_OVERRIDE;
1620

    
1621
  Representation from() const { return value()->representation(); }
1622
  Representation to() const { return representation(); }
1623
  bool deoptimize_on_minus_zero() const {
1624
    return CheckFlag(kBailoutOnMinusZero);
1625
  }
1626
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1627
    return from();
1628
  }
1629

    
1630
  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
1631

    
1632
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1633

    
1634
  DECLARE_CONCRETE_INSTRUCTION(Change)
1635

    
1636
 protected:
1637
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
1638

    
1639
 private:
1640
  virtual bool IsDeletable() const V8_OVERRIDE {
1641
    return !from().IsTagged() || value()->type().IsSmi();
1642
  }
1643
};
1644

    
1645

    
1646
class HClampToUint8 V8_FINAL : public HUnaryOperation {
1647
 public:
1648
  DECLARE_INSTRUCTION_FACTORY_P1(HClampToUint8, HValue*);
1649

    
1650
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1651
    return Representation::None();
1652
  }
1653

    
1654
  DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
1655

    
1656
 protected:
1657
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
1658

    
1659
 private:
1660
  explicit HClampToUint8(HValue* value)
1661
      : HUnaryOperation(value) {
1662
    set_representation(Representation::Integer32());
1663
    SetFlag(kAllowUndefinedAsNaN);
1664
    SetFlag(kUseGVN);
1665
  }
1666

    
1667
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
1668
};
1669

    
1670

    
1671
enum RemovableSimulate {
1672
  REMOVABLE_SIMULATE,
1673
  FIXED_SIMULATE
1674
};
1675

    
1676

    
1677
class HSimulate V8_FINAL : public HInstruction {
1678
 public:
1679
  HSimulate(BailoutId ast_id,
1680
            int pop_count,
1681
            Zone* zone,
1682
            RemovableSimulate removable)
1683
      : ast_id_(ast_id),
1684
        pop_count_(pop_count),
1685
        values_(2, zone),
1686
        assigned_indexes_(2, zone),
1687
        zone_(zone),
1688
        removable_(removable) {}
1689
  ~HSimulate() {}
1690

    
1691
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1692

    
1693
  bool HasAstId() const { return !ast_id_.IsNone(); }
1694
  BailoutId ast_id() const { return ast_id_; }
1695
  void set_ast_id(BailoutId id) {
1696
    ASSERT(!HasAstId());
1697
    ast_id_ = id;
1698
  }
1699

    
1700
  int pop_count() const { return pop_count_; }
1701
  const ZoneList<HValue*>* values() const { return &values_; }
1702
  int GetAssignedIndexAt(int index) const {
1703
    ASSERT(HasAssignedIndexAt(index));
1704
    return assigned_indexes_[index];
1705
  }
1706
  bool HasAssignedIndexAt(int index) const {
1707
    return assigned_indexes_[index] != kNoIndex;
1708
  }
1709
  void AddAssignedValue(int index, HValue* value) {
1710
    AddValue(index, value);
1711
  }
1712
  void AddPushedValue(HValue* value) {
1713
    AddValue(kNoIndex, value);
1714
  }
1715
  int ToOperandIndex(int environment_index) {
1716
    for (int i = 0; i < assigned_indexes_.length(); ++i) {
1717
      if (assigned_indexes_[i] == environment_index) return i;
1718
    }
1719
    return -1;
1720
  }
1721
  virtual int OperandCount() V8_OVERRIDE { return values_.length(); }
1722
  virtual HValue* OperandAt(int index) const V8_OVERRIDE {
1723
    return values_[index];
1724
  }
1725

    
1726
  virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
1727
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1728
    return Representation::None();
1729
  }
1730

    
1731
  void MergeWith(ZoneList<HSimulate*>* list);
1732
  bool is_candidate_for_removal() { return removable_ == REMOVABLE_SIMULATE; }
1733

    
1734
  // Replay effects of this instruction on the given environment.
1735
  void ReplayEnvironment(HEnvironment* env);
1736

    
1737
  DECLARE_CONCRETE_INSTRUCTION(Simulate)
1738

    
1739
#ifdef DEBUG
1740
  virtual void Verify() V8_OVERRIDE;
1741
  void set_closure(Handle<JSFunction> closure) { closure_ = closure; }
1742
  Handle<JSFunction> closure() const { return closure_; }
1743
#endif
1744

    
1745
 protected:
1746
  virtual void InternalSetOperandAt(int index, HValue* value) V8_OVERRIDE {
1747
    values_[index] = value;
1748
  }
1749

    
1750
 private:
1751
  static const int kNoIndex = -1;
1752
  void AddValue(int index, HValue* value) {
1753
    assigned_indexes_.Add(index, zone_);
1754
    // Resize the list of pushed values.
1755
    values_.Add(NULL, zone_);
1756
    // Set the operand through the base method in HValue to make sure that the
1757
    // use lists are correctly updated.
1758
    SetOperandAt(values_.length() - 1, value);
1759
  }
1760
  bool HasValueForIndex(int index) {
1761
    for (int i = 0; i < assigned_indexes_.length(); ++i) {
1762
      if (assigned_indexes_[i] == index) return true;
1763
    }
1764
    return false;
1765
  }
1766
  BailoutId ast_id_;
1767
  int pop_count_;
1768
  ZoneList<HValue*> values_;
1769
  ZoneList<int> assigned_indexes_;
1770
  Zone* zone_;
1771
  RemovableSimulate removable_;
1772

    
1773
#ifdef DEBUG
1774
  Handle<JSFunction> closure_;
1775
#endif
1776
};
1777

    
1778

    
1779
class HEnvironmentMarker V8_FINAL : public HTemplateInstruction<1> {
1780
 public:
1781
  enum Kind { BIND, LOOKUP };
1782

    
1783
  DECLARE_INSTRUCTION_FACTORY_P2(HEnvironmentMarker, Kind, int);
1784

    
1785
  Kind kind() { return kind_; }
1786
  int index() { return index_; }
1787
  HSimulate* next_simulate() { return next_simulate_; }
1788
  void set_next_simulate(HSimulate* simulate) {
1789
    next_simulate_ = simulate;
1790
  }
1791

    
1792
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1793
    return Representation::None();
1794
  }
1795

    
1796
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1797

    
1798
#ifdef DEBUG
1799
  void set_closure(Handle<JSFunction> closure) {
1800
    ASSERT(closure_.is_null());
1801
    ASSERT(!closure.is_null());
1802
    closure_ = closure;
1803
  }
1804
  Handle<JSFunction> closure() const { return closure_; }
1805
#endif
1806

    
1807
  DECLARE_CONCRETE_INSTRUCTION(EnvironmentMarker);
1808

    
1809
 private:
1810
  HEnvironmentMarker(Kind kind, int index)
1811
      : kind_(kind), index_(index), next_simulate_(NULL) { }
1812

    
1813
  Kind kind_;
1814
  int index_;
1815
  HSimulate* next_simulate_;
1816

    
1817
#ifdef DEBUG
1818
  Handle<JSFunction> closure_;
1819
#endif
1820
};
1821

    
1822

    
1823
class HStackCheck V8_FINAL : public HTemplateInstruction<1> {
1824
 public:
1825
  enum Type {
1826
    kFunctionEntry,
1827
    kBackwardsBranch
1828
  };
1829

    
1830
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HStackCheck, Type);
1831

    
1832
  HValue* context() { return OperandAt(0); }
1833

    
1834
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1835
    return Representation::Tagged();
1836
  }
1837

    
1838
  void Eliminate() {
1839
    // The stack check eliminator might try to eliminate the same stack
1840
    // check instruction multiple times.
1841
    if (IsLinked()) {
1842
      DeleteAndReplaceWith(NULL);
1843
    }
1844
  }
1845

    
1846
  bool is_function_entry() { return type_ == kFunctionEntry; }
1847
  bool is_backwards_branch() { return type_ == kBackwardsBranch; }
1848

    
1849
  DECLARE_CONCRETE_INSTRUCTION(StackCheck)
1850

    
1851
 private:
1852
  HStackCheck(HValue* context, Type type) : type_(type) {
1853
    SetOperandAt(0, context);
1854
    SetGVNFlag(kChangesNewSpacePromotion);
1855
  }
1856

    
1857
  Type type_;
1858
};
1859

    
1860

    
1861
enum InliningKind {
1862
  NORMAL_RETURN,          // Normal function/method call and return.
1863
  DROP_EXTRA_ON_RETURN,   // Drop an extra value from the environment on return.
1864
  CONSTRUCT_CALL_RETURN,  // Either use allocated receiver or return value.
1865
  GETTER_CALL_RETURN,     // Returning from a getter, need to restore context.
1866
  SETTER_CALL_RETURN      // Use the RHS of the assignment as the return value.
1867
};
1868

    
1869

    
1870
class HArgumentsObject;
1871

    
1872

    
1873
class HEnterInlined V8_FINAL : public HTemplateInstruction<0> {
1874
 public:
1875
  static HEnterInlined* New(Zone* zone,
1876
                            HValue* context,
1877
                            Handle<JSFunction> closure,
1878
                            int arguments_count,
1879
                            FunctionLiteral* function,
1880
                            InliningKind inlining_kind,
1881
                            Variable* arguments_var,
1882
                            HArgumentsObject* arguments_object,
1883
                            bool undefined_receiver) {
1884
    return new(zone) HEnterInlined(closure, arguments_count, function,
1885
                                   inlining_kind, arguments_var,
1886
                                   arguments_object, undefined_receiver, zone);
1887
  }
1888

    
1889
  void RegisterReturnTarget(HBasicBlock* return_target, Zone* zone);
1890
  ZoneList<HBasicBlock*>* return_targets() { return &return_targets_; }
1891

    
1892
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1893

    
1894
  Handle<JSFunction> closure() const { return closure_; }
1895
  int arguments_count() const { return arguments_count_; }
1896
  bool arguments_pushed() const { return arguments_pushed_; }
1897
  void set_arguments_pushed() { arguments_pushed_ = true; }
1898
  FunctionLiteral* function() const { return function_; }
1899
  InliningKind inlining_kind() const { return inlining_kind_; }
1900
  bool undefined_receiver() const { return undefined_receiver_; }
1901

    
1902
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1903
    return Representation::None();
1904
  }
1905

    
1906
  Variable* arguments_var() { return arguments_var_; }
1907
  HArgumentsObject* arguments_object() { return arguments_object_; }
1908

    
1909
  DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
1910

    
1911
 private:
1912
  HEnterInlined(Handle<JSFunction> closure,
1913
                int arguments_count,
1914
                FunctionLiteral* function,
1915
                InliningKind inlining_kind,
1916
                Variable* arguments_var,
1917
                HArgumentsObject* arguments_object,
1918
                bool undefined_receiver,
1919
                Zone* zone)
1920
      : closure_(closure),
1921
        arguments_count_(arguments_count),
1922
        arguments_pushed_(false),
1923
        function_(function),
1924
        inlining_kind_(inlining_kind),
1925
        arguments_var_(arguments_var),
1926
        arguments_object_(arguments_object),
1927
        undefined_receiver_(undefined_receiver),
1928
        return_targets_(2, zone) {
1929
  }
1930

    
1931
  Handle<JSFunction> closure_;
1932
  int arguments_count_;
1933
  bool arguments_pushed_;
1934
  FunctionLiteral* function_;
1935
  InliningKind inlining_kind_;
1936
  Variable* arguments_var_;
1937
  HArgumentsObject* arguments_object_;
1938
  bool undefined_receiver_;
1939
  ZoneList<HBasicBlock*> return_targets_;
1940
};
1941

    
1942

    
1943
class HLeaveInlined V8_FINAL : public HTemplateInstruction<0> {
1944
 public:
1945
  HLeaveInlined(HEnterInlined* entry,
1946
                int drop_count)
1947
      : entry_(entry),
1948
        drop_count_(drop_count) { }
1949

    
1950
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1951
    return Representation::None();
1952
  }
1953

    
1954
  virtual int argument_delta() const V8_OVERRIDE {
1955
    return entry_->arguments_pushed() ? -drop_count_ : 0;
1956
  }
1957

    
1958
  DECLARE_CONCRETE_INSTRUCTION(LeaveInlined)
1959

    
1960
 private:
1961
  HEnterInlined* entry_;
1962
  int drop_count_;
1963
};
1964

    
1965

    
1966
class HPushArgument V8_FINAL : public HUnaryOperation {
1967
 public:
1968
  DECLARE_INSTRUCTION_FACTORY_P1(HPushArgument, HValue*);
1969

    
1970
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1971
    return Representation::Tagged();
1972
  }
1973

    
1974
  virtual int argument_delta() const V8_OVERRIDE { return 1; }
1975
  HValue* argument() { return OperandAt(0); }
1976

    
1977
  DECLARE_CONCRETE_INSTRUCTION(PushArgument)
1978

    
1979
 private:
1980
  explicit HPushArgument(HValue* value) : HUnaryOperation(value) {
1981
    set_representation(Representation::Tagged());
1982
  }
1983
};
1984

    
1985

    
1986
class HThisFunction V8_FINAL : public HTemplateInstruction<0> {
1987
 public:
1988
  DECLARE_INSTRUCTION_FACTORY_P0(HThisFunction);
1989

    
1990
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
1991
    return Representation::None();
1992
  }
1993

    
1994
  DECLARE_CONCRETE_INSTRUCTION(ThisFunction)
1995

    
1996
 protected:
1997
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
1998

    
1999
 private:
2000
  HThisFunction() {
2001
    set_representation(Representation::Tagged());
2002
    SetFlag(kUseGVN);
2003
  }
2004

    
2005
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2006
};
2007

    
2008

    
2009
class HOuterContext V8_FINAL : public HUnaryOperation {
2010
 public:
2011
  DECLARE_INSTRUCTION_FACTORY_P1(HOuterContext, HValue*);
2012

    
2013
  DECLARE_CONCRETE_INSTRUCTION(OuterContext);
2014

    
2015
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2016
    return Representation::Tagged();
2017
  }
2018

    
2019
 protected:
2020
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
2021

    
2022
 private:
2023
  explicit HOuterContext(HValue* inner) : HUnaryOperation(inner) {
2024
    set_representation(Representation::Tagged());
2025
    SetFlag(kUseGVN);
2026
  }
2027

    
2028
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2029
};
2030

    
2031

    
2032
class HDeclareGlobals V8_FINAL : public HUnaryOperation {
2033
 public:
2034
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HDeclareGlobals,
2035
                                              Handle<FixedArray>,
2036
                                              int);
2037

    
2038
  HValue* context() { return OperandAt(0); }
2039
  Handle<FixedArray> pairs() const { return pairs_; }
2040
  int flags() const { return flags_; }
2041

    
2042
  DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals)
2043

    
2044
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2045
    return Representation::Tagged();
2046
  }
2047

    
2048
 private:
2049
  HDeclareGlobals(HValue* context,
2050
                  Handle<FixedArray> pairs,
2051
                  int flags)
2052
      : HUnaryOperation(context),
2053
        pairs_(pairs),
2054
        flags_(flags) {
2055
    set_representation(Representation::Tagged());
2056
    SetAllSideEffects();
2057
  }
2058

    
2059
  Handle<FixedArray> pairs_;
2060
  int flags_;
2061
};
2062

    
2063

    
2064
class HGlobalObject V8_FINAL : public HUnaryOperation {
2065
 public:
2066
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P0(HGlobalObject);
2067

    
2068
  DECLARE_CONCRETE_INSTRUCTION(GlobalObject)
2069

    
2070
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2071
    return Representation::Tagged();
2072
  }
2073

    
2074
 protected:
2075
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
2076

    
2077
 private:
2078
  explicit HGlobalObject(HValue* context) : HUnaryOperation(context) {
2079
    set_representation(Representation::Tagged());
2080
    SetFlag(kUseGVN);
2081
  }
2082

    
2083
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2084
};
2085

    
2086

    
2087
class HGlobalReceiver V8_FINAL : public HUnaryOperation {
2088
 public:
2089
  DECLARE_INSTRUCTION_FACTORY_P1(HGlobalReceiver, HValue*);
2090

    
2091
  DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver)
2092

    
2093
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2094
    return Representation::Tagged();
2095
  }
2096

    
2097
 protected:
2098
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
2099

    
2100
 private:
2101
  explicit HGlobalReceiver(HValue* global_object)
2102
      : HUnaryOperation(global_object) {
2103
    set_representation(Representation::Tagged());
2104
    SetFlag(kUseGVN);
2105
  }
2106

    
2107
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2108
};
2109

    
2110

    
2111
template <int V>
2112
class HCall : public HTemplateInstruction<V> {
2113
 public:
2114
  // The argument count includes the receiver.
2115
  explicit HCall<V>(int argument_count) : argument_count_(argument_count) {
2116
    this->set_representation(Representation::Tagged());
2117
    this->SetAllSideEffects();
2118
  }
2119

    
2120
  virtual HType CalculateInferredType() V8_FINAL V8_OVERRIDE {
2121
    return HType::Tagged();
2122
  }
2123

    
2124
  virtual int argument_count() const {
2125
    return argument_count_;
2126
  }
2127

    
2128
  virtual int argument_delta() const V8_OVERRIDE {
2129
    return -argument_count();
2130
  }
2131

    
2132
  virtual bool IsCall() V8_FINAL V8_OVERRIDE { return true; }
2133

    
2134
 private:
2135
  int argument_count_;
2136
};
2137

    
2138

    
2139
class HUnaryCall : public HCall<1> {
2140
 public:
2141
  HUnaryCall(HValue* value, int argument_count)
2142
      : HCall<1>(argument_count) {
2143
    SetOperandAt(0, value);
2144
  }
2145

    
2146
  virtual Representation RequiredInputRepresentation(
2147
      int index) V8_FINAL V8_OVERRIDE {
2148
    return Representation::Tagged();
2149
  }
2150

    
2151
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2152

    
2153
  HValue* value() { return OperandAt(0); }
2154
};
2155

    
2156

    
2157
class HBinaryCall : public HCall<2> {
2158
 public:
2159
  HBinaryCall(HValue* first, HValue* second, int argument_count)
2160
      : HCall<2>(argument_count) {
2161
    SetOperandAt(0, first);
2162
    SetOperandAt(1, second);
2163
  }
2164

    
2165
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2166

    
2167
  virtual Representation RequiredInputRepresentation(
2168
      int index) V8_FINAL V8_OVERRIDE {
2169
    return Representation::Tagged();
2170
  }
2171

    
2172
  HValue* first() { return OperandAt(0); }
2173
  HValue* second() { return OperandAt(1); }
2174
};
2175

    
2176

    
2177
class HInvokeFunction V8_FINAL : public HBinaryCall {
2178
 public:
2179
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInvokeFunction, HValue*, int);
2180

    
2181
  HInvokeFunction(HValue* context,
2182
                  HValue* function,
2183
                  Handle<JSFunction> known_function,
2184
                  int argument_count)
2185
      : HBinaryCall(context, function, argument_count),
2186
        known_function_(known_function) {
2187
    formal_parameter_count_ = known_function.is_null()
2188
        ? 0 : known_function->shared()->formal_parameter_count();
2189
  }
2190

    
2191
  static HInvokeFunction* New(Zone* zone,
2192
                              HValue* context,
2193
                              HValue* function,
2194
                              Handle<JSFunction> known_function,
2195
                              int argument_count) {
2196
    return new(zone) HInvokeFunction(context, function,
2197
                                     known_function, argument_count);
2198
  }
2199

    
2200
  HValue* context() { return first(); }
2201
  HValue* function() { return second(); }
2202
  Handle<JSFunction> known_function() { return known_function_; }
2203
  int formal_parameter_count() const { return formal_parameter_count_; }
2204

    
2205
  DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
2206

    
2207
 private:
2208
  HInvokeFunction(HValue* context, HValue* function, int argument_count)
2209
      : HBinaryCall(context, function, argument_count) {
2210
  }
2211

    
2212
  Handle<JSFunction> known_function_;
2213
  int formal_parameter_count_;
2214
};
2215

    
2216

    
2217
class HCallConstantFunction V8_FINAL : public HCall<0> {
2218
 public:
2219
  DECLARE_INSTRUCTION_FACTORY_P2(HCallConstantFunction,
2220
                                 Handle<JSFunction>,
2221
                                 int);
2222

    
2223
  Handle<JSFunction> function() const { return function_; }
2224
  int formal_parameter_count() const { return formal_parameter_count_; }
2225

    
2226
  bool IsApplyFunction() const {
2227
    return function_->code() ==
2228
        function_->GetIsolate()->builtins()->builtin(Builtins::kFunctionApply);
2229
  }
2230

    
2231
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2232

    
2233
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2234
    return Representation::None();
2235
  }
2236

    
2237
  DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction)
2238

    
2239
 private:
2240
  HCallConstantFunction(Handle<JSFunction> function, int argument_count)
2241
      : HCall<0>(argument_count),
2242
        function_(function),
2243
        formal_parameter_count_(function->shared()->formal_parameter_count()) {}
2244

    
2245
  Handle<JSFunction> function_;
2246
  int formal_parameter_count_;
2247
};
2248

    
2249

    
2250
class HCallKeyed V8_FINAL : public HBinaryCall {
2251
 public:
2252
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallKeyed, HValue*, int);
2253

    
2254
  HValue* context() { return first(); }
2255
  HValue* key() { return second(); }
2256

    
2257
  DECLARE_CONCRETE_INSTRUCTION(CallKeyed)
2258

    
2259
 private:
2260
  HCallKeyed(HValue* context, HValue* key, int argument_count)
2261
      : HBinaryCall(context, key, argument_count) {
2262
  }
2263
};
2264

    
2265

    
2266
class HCallNamed V8_FINAL : public HUnaryCall {
2267
 public:
2268
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallNamed, Handle<String>, int);
2269

    
2270
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2271

    
2272
  HValue* context() { return value(); }
2273
  Handle<String> name() const { return name_; }
2274

    
2275
  DECLARE_CONCRETE_INSTRUCTION(CallNamed)
2276

    
2277
 private:
2278
  HCallNamed(HValue* context, Handle<String> name, int argument_count)
2279
      : HUnaryCall(context, argument_count), name_(name) {
2280
  }
2281

    
2282
  Handle<String> name_;
2283
};
2284

    
2285

    
2286
class HCallFunction V8_FINAL : public HBinaryCall {
2287
 public:
2288
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallFunction, HValue*, int);
2289

    
2290
  HValue* context() { return first(); }
2291
  HValue* function() { return second(); }
2292

    
2293
  DECLARE_CONCRETE_INSTRUCTION(CallFunction)
2294

    
2295
 private:
2296
  HCallFunction(HValue* context, HValue* function, int argument_count)
2297
      : HBinaryCall(context, function, argument_count) {
2298
  }
2299
};
2300

    
2301

    
2302
class HCallGlobal V8_FINAL : public HUnaryCall {
2303
 public:
2304
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallGlobal, Handle<String>, int);
2305

    
2306
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2307

    
2308
  HValue* context() { return value(); }
2309
  Handle<String> name() const { return name_; }
2310

    
2311
  DECLARE_CONCRETE_INSTRUCTION(CallGlobal)
2312

    
2313
 private:
2314
  HCallGlobal(HValue* context, Handle<String> name, int argument_count)
2315
      : HUnaryCall(context, argument_count), name_(name) {
2316
  }
2317

    
2318
  Handle<String> name_;
2319
};
2320

    
2321

    
2322
class HCallKnownGlobal V8_FINAL : public HCall<0> {
2323
 public:
2324
  DECLARE_INSTRUCTION_FACTORY_P2(HCallKnownGlobal, Handle<JSFunction>, int);
2325

    
2326
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2327

    
2328
  Handle<JSFunction> target() const { return target_; }
2329
  int formal_parameter_count() const { return formal_parameter_count_; }
2330

    
2331
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2332
    return Representation::None();
2333
  }
2334

    
2335
  DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal)
2336

    
2337
 private:
2338
  HCallKnownGlobal(Handle<JSFunction> target, int argument_count)
2339
      : HCall<0>(argument_count),
2340
        target_(target),
2341
        formal_parameter_count_(target->shared()->formal_parameter_count()) { }
2342

    
2343
  Handle<JSFunction> target_;
2344
  int formal_parameter_count_;
2345
};
2346

    
2347

    
2348
class HCallNew V8_FINAL : public HBinaryCall {
2349
 public:
2350
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallNew, HValue*, int);
2351

    
2352
  HValue* context() { return first(); }
2353
  HValue* constructor() { return second(); }
2354

    
2355
  DECLARE_CONCRETE_INSTRUCTION(CallNew)
2356

    
2357
 private:
2358
  HCallNew(HValue* context, HValue* constructor, int argument_count)
2359
      : HBinaryCall(context, constructor, argument_count) {}
2360
};
2361

    
2362

    
2363
class HCallNewArray V8_FINAL : public HBinaryCall {
2364
 public:
2365
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HCallNewArray,
2366
                                              HValue*,
2367
                                              int,
2368
                                              Handle<Cell>,
2369
                                              ElementsKind);
2370

    
2371
  HValue* context() { return first(); }
2372
  HValue* constructor() { return second(); }
2373

    
2374
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2375

    
2376
  Handle<Cell> property_cell() const {
2377
    return type_cell_;
2378
  }
2379

    
2380
  ElementsKind elements_kind() const { return elements_kind_; }
2381

    
2382
  DECLARE_CONCRETE_INSTRUCTION(CallNewArray)
2383

    
2384
 private:
2385
  HCallNewArray(HValue* context, HValue* constructor, int argument_count,
2386
                Handle<Cell> type_cell, ElementsKind elements_kind)
2387
      : HBinaryCall(context, constructor, argument_count),
2388
        elements_kind_(elements_kind),
2389
        type_cell_(type_cell) {}
2390

    
2391
  ElementsKind elements_kind_;
2392
  Handle<Cell> type_cell_;
2393
};
2394

    
2395

    
2396
class HCallRuntime V8_FINAL : public HCall<1> {
2397
 public:
2398
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HCallRuntime,
2399
                                              Handle<String>,
2400
                                              const Runtime::Function*,
2401
                                              int);
2402

    
2403
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2404

    
2405
  HValue* context() { return OperandAt(0); }
2406
  const Runtime::Function* function() const { return c_function_; }
2407
  Handle<String> name() const { return name_; }
2408
  SaveFPRegsMode save_doubles() const { return save_doubles_; }
2409
  void set_save_doubles(SaveFPRegsMode save_doubles) {
2410
    save_doubles_ = save_doubles;
2411
  }
2412

    
2413
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2414
    return Representation::Tagged();
2415
  }
2416

    
2417
  DECLARE_CONCRETE_INSTRUCTION(CallRuntime)
2418

    
2419
 private:
2420
  HCallRuntime(HValue* context,
2421
               Handle<String> name,
2422
               const Runtime::Function* c_function,
2423
               int argument_count)
2424
      : HCall<1>(argument_count), c_function_(c_function), name_(name),
2425
        save_doubles_(kDontSaveFPRegs) {
2426
    SetOperandAt(0, context);
2427
  }
2428

    
2429
  const Runtime::Function* c_function_;
2430
  Handle<String> name_;
2431
  SaveFPRegsMode save_doubles_;
2432
};
2433

    
2434

    
2435
class HMapEnumLength V8_FINAL : public HUnaryOperation {
2436
 public:
2437
  DECLARE_INSTRUCTION_FACTORY_P1(HMapEnumLength, HValue*);
2438

    
2439
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2440
    return Representation::Tagged();
2441
  }
2442

    
2443
  DECLARE_CONCRETE_INSTRUCTION(MapEnumLength)
2444

    
2445
 protected:
2446
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
2447

    
2448
 private:
2449
  explicit HMapEnumLength(HValue* value)
2450
      : HUnaryOperation(value, HType::Smi()) {
2451
    set_representation(Representation::Smi());
2452
    SetFlag(kUseGVN);
2453
    SetGVNFlag(kDependsOnMaps);
2454
  }
2455

    
2456
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2457
};
2458

    
2459

    
2460
class HElementsKind V8_FINAL : public HUnaryOperation {
2461
 public:
2462
  explicit HElementsKind(HValue* value) : HUnaryOperation(value) {
2463
    set_representation(Representation::Integer32());
2464
    SetFlag(kUseGVN);
2465
    SetGVNFlag(kDependsOnElementsKind);
2466
  }
2467

    
2468
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2469
    return Representation::Tagged();
2470
  }
2471

    
2472
  DECLARE_CONCRETE_INSTRUCTION(ElementsKind)
2473

    
2474
 protected:
2475
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
2476

    
2477
 private:
2478
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2479
};
2480

    
2481

    
2482
class HUnaryMathOperation V8_FINAL : public HTemplateInstruction<2> {
2483
 public:
2484
  static HInstruction* New(Zone* zone,
2485
                           HValue* context,
2486
                           HValue* value,
2487
                           BuiltinFunctionId op);
2488

    
2489
  HValue* context() { return OperandAt(0); }
2490
  HValue* value() { return OperandAt(1); }
2491

    
2492
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2493

    
2494
  virtual HValue* EnsureAndPropagateNotMinusZero(
2495
      BitVector* visited) V8_OVERRIDE;
2496

    
2497
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2498
    if (index == 0) {
2499
      return Representation::Tagged();
2500
    } else {
2501
      switch (op_) {
2502
        case kMathFloor:
2503
        case kMathRound:
2504
        case kMathSqrt:
2505
        case kMathPowHalf:
2506
        case kMathLog:
2507
        case kMathExp:
2508
        case kMathSin:
2509
        case kMathCos:
2510
        case kMathTan:
2511
          return Representation::Double();
2512
        case kMathAbs:
2513
          return representation();
2514
        default:
2515
          UNREACHABLE();
2516
          return Representation::None();
2517
      }
2518
    }
2519
  }
2520

    
2521
  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
2522

    
2523
  virtual HValue* Canonicalize() V8_OVERRIDE;
2524
  virtual Representation RepresentationFromInputs() V8_OVERRIDE;
2525

    
2526
  BuiltinFunctionId op() const { return op_; }
2527
  const char* OpName() const;
2528

    
2529
  DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation)
2530

    
2531
 protected:
2532
  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2533
    HUnaryMathOperation* b = HUnaryMathOperation::cast(other);
2534
    return op_ == b->op();
2535
  }
2536

    
2537
 private:
2538
  HUnaryMathOperation(HValue* context, HValue* value, BuiltinFunctionId op)
2539
      : HTemplateInstruction<2>(HType::TaggedNumber()), op_(op) {
2540
    SetOperandAt(0, context);
2541
    SetOperandAt(1, value);
2542
    switch (op) {
2543
      case kMathFloor:
2544
      case kMathRound:
2545
        set_representation(Representation::Integer32());
2546
        break;
2547
      case kMathAbs:
2548
        // Not setting representation here: it is None intentionally.
2549
        SetFlag(kFlexibleRepresentation);
2550
        // TODO(svenpanne) This flag is actually only needed if representation()
2551
        // is tagged, and not when it is an unboxed double or unboxed integer.
2552
        SetGVNFlag(kChangesNewSpacePromotion);
2553
        break;
2554
      case kMathLog:
2555
      case kMathSin:
2556
      case kMathCos:
2557
      case kMathTan:
2558
        set_representation(Representation::Double());
2559
        // These operations use the TranscendentalCache, so they may allocate.
2560
        SetGVNFlag(kChangesNewSpacePromotion);
2561
        break;
2562
      case kMathExp:
2563
      case kMathSqrt:
2564
      case kMathPowHalf:
2565
        set_representation(Representation::Double());
2566
        break;
2567
      default:
2568
        UNREACHABLE();
2569
    }
2570
    SetFlag(kUseGVN);
2571
    SetFlag(kAllowUndefinedAsNaN);
2572
  }
2573

    
2574
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2575

    
2576
  BuiltinFunctionId op_;
2577
};
2578

    
2579

    
2580
class HLoadRoot V8_FINAL : public HTemplateInstruction<0> {
2581
 public:
2582
  DECLARE_INSTRUCTION_FACTORY_P1(HLoadRoot, Heap::RootListIndex);
2583
  DECLARE_INSTRUCTION_FACTORY_P2(HLoadRoot, Heap::RootListIndex, HType);
2584

    
2585
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2586
    return Representation::None();
2587
  }
2588

    
2589
  Heap::RootListIndex index() const { return index_; }
2590

    
2591
  DECLARE_CONCRETE_INSTRUCTION(LoadRoot)
2592

    
2593
 protected:
2594
  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2595
    HLoadRoot* b = HLoadRoot::cast(other);
2596
    return index_ == b->index_;
2597
  }
2598

    
2599
 private:
2600
  HLoadRoot(Heap::RootListIndex index, HType type = HType::Tagged())
2601
      : HTemplateInstruction<0>(type), index_(index) {
2602
    SetFlag(kUseGVN);
2603
    // TODO(bmeurer): We'll need kDependsOnRoots once we add the
2604
    // corresponding HStoreRoot instruction.
2605
    SetGVNFlag(kDependsOnCalls);
2606
  }
2607

    
2608
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2609

    
2610
  const Heap::RootListIndex index_;
2611
};
2612

    
2613

    
2614
class HLoadExternalArrayPointer V8_FINAL : public HUnaryOperation {
2615
 public:
2616
  DECLARE_INSTRUCTION_FACTORY_P1(HLoadExternalArrayPointer, HValue*);
2617

    
2618
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2619
    return Representation::Tagged();
2620
  }
2621

    
2622
  virtual HType CalculateInferredType() V8_OVERRIDE {
2623
    return HType::None();
2624
  }
2625

    
2626
  DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer)
2627

    
2628
 protected:
2629
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
2630

    
2631
 private:
2632
  explicit HLoadExternalArrayPointer(HValue* value)
2633
      : HUnaryOperation(value) {
2634
    set_representation(Representation::External());
2635
    // The result of this instruction is idempotent as long as its inputs don't
2636
    // change.  The external array of a specialized array elements object cannot
2637
    // change once set, so it's no necessary to introduce any additional
2638
    // dependencies on top of the inputs.
2639
    SetFlag(kUseGVN);
2640
  }
2641

    
2642
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
2643
};
2644

    
2645

    
2646
class HCheckMaps V8_FINAL : public HTemplateInstruction<2> {
2647
 public:
2648
  static HCheckMaps* New(Zone* zone, HValue* context, HValue* value,
2649
                         Handle<Map> map, CompilationInfo* info,
2650
                         HValue *typecheck = NULL);
2651
  static HCheckMaps* New(Zone* zone, HValue* context,
2652
                         HValue* value, SmallMapList* maps,
2653
                         HValue *typecheck = NULL) {
2654
    HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck);
2655
    for (int i = 0; i < maps->length(); i++) {
2656
      check_map->Add(maps->at(i), zone);
2657
    }
2658
    return check_map;
2659
  }
2660

    
2661
  bool CanOmitMapChecks() { return omit_; }
2662

    
2663
  virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
2664
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2665
    return Representation::Tagged();
2666
  }
2667
  virtual void HandleSideEffectDominator(GVNFlag side_effect,
2668
                                         HValue* dominator) V8_OVERRIDE;
2669
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2670

    
2671
  HValue* value() { return OperandAt(0); }
2672

    
2673
  Unique<Map> first_map() const { return map_set_.at(0); }
2674
  UniqueSet<Map> map_set() const { return map_set_; }
2675

    
2676
  bool has_migration_target() const {
2677
    return has_migration_target_;
2678
  }
2679

    
2680
  DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
2681

    
2682
 protected:
2683
  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2684
    return this->map_set_.Equals(&HCheckMaps::cast(other)->map_set_);
2685
  }
2686

    
2687
  virtual int RedefinedOperandIndex() { return 0; }
2688

    
2689
 private:
2690
  void Add(Handle<Map> map, Zone* zone) {
2691
    map_set_.Add(Unique<Map>(map), zone);
2692
    if (!has_migration_target_ && map->is_migration_target()) {
2693
      has_migration_target_ = true;
2694
      SetGVNFlag(kChangesNewSpacePromotion);
2695
    }
2696
  }
2697

    
2698
  // Clients should use one of the static New* methods above.
2699
  HCheckMaps(HValue* value, Zone *zone, HValue* typecheck)
2700
      : HTemplateInstruction<2>(value->type()),
2701
        omit_(false), has_migration_target_(false) {
2702
    SetOperandAt(0, value);
2703
    // Use the object value for the dependency if NULL is passed.
2704
    SetOperandAt(1, typecheck != NULL ? typecheck : value);
2705
    set_representation(Representation::Tagged());
2706
    SetFlag(kUseGVN);
2707
    SetFlag(kTrackSideEffectDominators);
2708
    SetGVNFlag(kDependsOnMaps);
2709
    SetGVNFlag(kDependsOnElementsKind);
2710
  }
2711

    
2712
  bool omit_;
2713
  bool has_migration_target_;
2714
  UniqueSet<Map> map_set_;
2715
};
2716

    
2717

    
2718
class HCheckValue V8_FINAL : public HUnaryOperation {
2719
 public:
2720
  static HCheckValue* New(Zone* zone, HValue* context,
2721
                          HValue* value, Handle<JSFunction> func) {
2722
    bool in_new_space = zone->isolate()->heap()->InNewSpace(*func);
2723
    // NOTE: We create an uninitialized Unique and initialize it later.
2724
    // This is because a JSFunction can move due to GC during graph creation.
2725
    // TODO(titzer): This is a migration crutch. Replace with some kind of
2726
    // Uniqueness scope later.
2727
    Unique<JSFunction> target = Unique<JSFunction>::CreateUninitialized(func);
2728
    HCheckValue* check = new(zone) HCheckValue(value, target, in_new_space);
2729
    return check;
2730
  }
2731
  static HCheckValue* New(Zone* zone, HValue* context,
2732
                          HValue* value, Unique<HeapObject> target,
2733
                          bool object_in_new_space) {
2734
    return new(zone) HCheckValue(value, target, object_in_new_space);
2735
  }
2736

    
2737
  virtual void FinalizeUniqueness() V8_OVERRIDE {
2738
    object_ = Unique<HeapObject>(object_.handle());
2739
  }
2740

    
2741
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2742
    return Representation::Tagged();
2743
  }
2744
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2745

    
2746
  virtual HValue* Canonicalize() V8_OVERRIDE;
2747

    
2748
#ifdef DEBUG
2749
  virtual void Verify() V8_OVERRIDE;
2750
#endif
2751

    
2752
  Unique<HeapObject> object() const { return object_; }
2753
  bool object_in_new_space() const { return object_in_new_space_; }
2754

    
2755
  DECLARE_CONCRETE_INSTRUCTION(CheckValue)
2756

    
2757
 protected:
2758
  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2759
    HCheckValue* b = HCheckValue::cast(other);
2760
    return object_ == b->object_;
2761
  }
2762

    
2763
 private:
2764
  HCheckValue(HValue* value, Unique<HeapObject> object,
2765
               bool object_in_new_space)
2766
      : HUnaryOperation(value, value->type()),
2767
        object_(object),
2768
        object_in_new_space_(object_in_new_space) {
2769
    set_representation(Representation::Tagged());
2770
    SetFlag(kUseGVN);
2771
  }
2772

    
2773
  Unique<HeapObject> object_;
2774
  bool object_in_new_space_;
2775
};
2776

    
2777

    
2778
class HCheckInstanceType V8_FINAL : public HUnaryOperation {
2779
 public:
2780
  enum Check {
2781
    IS_SPEC_OBJECT,
2782
    IS_JS_ARRAY,
2783
    IS_STRING,
2784
    IS_INTERNALIZED_STRING,
2785
    LAST_INTERVAL_CHECK = IS_JS_ARRAY
2786
  };
2787

    
2788
  DECLARE_INSTRUCTION_FACTORY_P2(HCheckInstanceType, HValue*, Check);
2789

    
2790
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2791

    
2792
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2793
    return Representation::Tagged();
2794
  }
2795

    
2796
  virtual HValue* Canonicalize() V8_OVERRIDE;
2797

    
2798
  bool is_interval_check() const { return check_ <= LAST_INTERVAL_CHECK; }
2799
  void GetCheckInterval(InstanceType* first, InstanceType* last);
2800
  void GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag);
2801

    
2802
  DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType)
2803

    
2804
 protected:
2805
  // TODO(ager): It could be nice to allow the ommision of instance
2806
  // type checks if we have already performed an instance type check
2807
  // with a larger range.
2808
  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
2809
    HCheckInstanceType* b = HCheckInstanceType::cast(other);
2810
    return check_ == b->check_;
2811
  }
2812

    
2813
  virtual int RedefinedOperandIndex() { return 0; }
2814

    
2815
 private:
2816
  const char* GetCheckName();
2817

    
2818
  HCheckInstanceType(HValue* value, Check check)
2819
      : HUnaryOperation(value), check_(check) {
2820
    set_representation(Representation::Tagged());
2821
    SetFlag(kUseGVN);
2822
  }
2823

    
2824
  const Check check_;
2825
};
2826

    
2827

    
2828
class HCheckSmi V8_FINAL : public HUnaryOperation {
2829
 public:
2830
  DECLARE_INSTRUCTION_FACTORY_P1(HCheckSmi, HValue*);
2831

    
2832
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2833
    return Representation::Tagged();
2834
  }
2835

    
2836
  virtual HValue* Canonicalize() V8_OVERRIDE {
2837
    HType value_type = value()->type();
2838
    if (value_type.IsSmi()) {
2839
      return NULL;
2840
    }
2841
    return this;
2842
  }
2843

    
2844
  DECLARE_CONCRETE_INSTRUCTION(CheckSmi)
2845

    
2846
 protected:
2847
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
2848

    
2849
 private:
2850
  explicit HCheckSmi(HValue* value) : HUnaryOperation(value, HType::Smi()) {
2851
    set_representation(Representation::Smi());
2852
    SetFlag(kUseGVN);
2853
  }
2854
};
2855

    
2856

    
2857
class HCheckHeapObject V8_FINAL : public HUnaryOperation {
2858
 public:
2859
  DECLARE_INSTRUCTION_FACTORY_P1(HCheckHeapObject, HValue*);
2860

    
2861
  virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
2862
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
2863
    return Representation::Tagged();
2864
  }
2865

    
2866
#ifdef DEBUG
2867
  virtual void Verify() V8_OVERRIDE;
2868
#endif
2869

    
2870
  virtual HValue* Canonicalize() V8_OVERRIDE {
2871
    return value()->type().IsHeapObject() ? NULL : this;
2872
  }
2873

    
2874
  DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject)
2875

    
2876
 protected:
2877
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
2878

    
2879
 private:
2880
  explicit HCheckHeapObject(HValue* value)
2881
      : HUnaryOperation(value, HType::NonPrimitive()) {
2882
    set_representation(Representation::Tagged());
2883
    SetFlag(kUseGVN);
2884
  }
2885
};
2886

    
2887

    
2888
class InductionVariableData;
2889

    
2890

    
2891
struct InductionVariableLimitUpdate {
2892
  InductionVariableData* updated_variable;
2893
  HValue* limit;
2894
  bool limit_is_upper;
2895
  bool limit_is_included;
2896

    
2897
  InductionVariableLimitUpdate()
2898
      : updated_variable(NULL), limit(NULL),
2899
        limit_is_upper(false), limit_is_included(false) {}
2900
};
2901

    
2902

    
2903
class HBoundsCheck;
2904
class HPhi;
2905
class HConstant;
2906
class HBitwise;
2907

    
2908

    
2909
class InductionVariableData V8_FINAL : public ZoneObject {
2910
 public:
2911
  class InductionVariableCheck : public ZoneObject {
2912
   public:
2913
    HBoundsCheck* check() { return check_; }
2914
    InductionVariableCheck* next() { return next_; }
2915
    bool HasUpperLimit() { return upper_limit_ >= 0; }
2916
    int32_t upper_limit() {
2917
      ASSERT(HasUpperLimit());
2918
      return upper_limit_;
2919
    }
2920
    void set_upper_limit(int32_t upper_limit) {
2921
      upper_limit_ = upper_limit;
2922
    }
2923

    
2924
    bool processed() { return processed_; }
2925
    void set_processed() { processed_ = true; }
2926

    
2927
    InductionVariableCheck(HBoundsCheck* check,
2928
                           InductionVariableCheck* next,
2929
                           int32_t upper_limit = kNoLimit)
2930
        : check_(check), next_(next), upper_limit_(upper_limit),
2931
          processed_(false) {}
2932

    
2933
   private:
2934
    HBoundsCheck* check_;
2935
    InductionVariableCheck* next_;
2936
    int32_t upper_limit_;
2937
    bool processed_;
2938
  };
2939

    
2940
  class ChecksRelatedToLength : public ZoneObject {
2941
   public:
2942
    HValue* length() { return length_; }
2943
    ChecksRelatedToLength* next() { return next_; }
2944
    InductionVariableCheck* checks() { return checks_; }
2945

    
2946
    void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
2947
    void CloseCurrentBlock();
2948

    
2949
    ChecksRelatedToLength(HValue* length, ChecksRelatedToLength* next)
2950
      : length_(length), next_(next), checks_(NULL),
2951
        first_check_in_block_(NULL),
2952
        added_index_(NULL),
2953
        added_constant_(NULL),
2954
        current_and_mask_in_block_(0),
2955
        current_or_mask_in_block_(0) {}
2956

    
2957
   private:
2958
    void UseNewIndexInCurrentBlock(Token::Value token,
2959
                                   int32_t mask,
2960
                                   HValue* index_base,
2961
                                   HValue* context);
2962

    
2963
    HBoundsCheck* first_check_in_block() { return first_check_in_block_; }
2964
    HBitwise* added_index() { return added_index_; }
2965
    void set_added_index(HBitwise* index) { added_index_ = index; }
2966
    HConstant* added_constant() { return added_constant_; }
2967
    void set_added_constant(HConstant* constant) { added_constant_ = constant; }
2968
    int32_t current_and_mask_in_block() { return current_and_mask_in_block_; }
2969
    int32_t current_or_mask_in_block() { return current_or_mask_in_block_; }
2970
    int32_t current_upper_limit() { return current_upper_limit_; }
2971

    
2972
    HValue* length_;
2973
    ChecksRelatedToLength* next_;
2974
    InductionVariableCheck* checks_;
2975

    
2976
    HBoundsCheck* first_check_in_block_;
2977
    HBitwise* added_index_;
2978
    HConstant* added_constant_;
2979
    int32_t current_and_mask_in_block_;
2980
    int32_t current_or_mask_in_block_;
2981
    int32_t current_upper_limit_;
2982
  };
2983

    
2984
  struct LimitFromPredecessorBlock {
2985
    InductionVariableData* variable;
2986
    Token::Value token;
2987
    HValue* limit;
2988
    HBasicBlock* other_target;
2989

    
2990
    bool LimitIsValid() { return token != Token::ILLEGAL; }
2991

    
2992
    bool LimitIsIncluded() {
2993
      return Token::IsEqualityOp(token) ||
2994
          token == Token::GTE || token == Token::LTE;
2995
    }
2996
    bool LimitIsUpper() {
2997
      return token == Token::LTE || token == Token::LT || token == Token::NE;
2998
    }
2999

    
3000
    LimitFromPredecessorBlock()
3001
        : variable(NULL),
3002
          token(Token::ILLEGAL),
3003
          limit(NULL),
3004
          other_target(NULL) {}
3005
  };
3006

    
3007
  static const int32_t kNoLimit = -1;
3008

    
3009
  static InductionVariableData* ExaminePhi(HPhi* phi);
3010
  static void ComputeLimitFromPredecessorBlock(
3011
      HBasicBlock* block,
3012
      LimitFromPredecessorBlock* result);
3013
  static bool ComputeInductionVariableLimit(
3014
      HBasicBlock* block,
3015
      InductionVariableLimitUpdate* additional_limit);
3016

    
3017
  struct BitwiseDecompositionResult {
3018
    HValue* base;
3019
    int32_t and_mask;
3020
    int32_t or_mask;
3021
    HValue* context;
3022

    
3023
    BitwiseDecompositionResult()
3024
        : base(NULL), and_mask(0), or_mask(0), context(NULL) {}
3025
  };
3026
  static void DecomposeBitwise(HValue* value,
3027
                               BitwiseDecompositionResult* result);
3028

    
3029
  void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
3030

    
3031
  bool CheckIfBranchIsLoopGuard(Token::Value token,
3032
                                HBasicBlock* current_branch,
3033
                                HBasicBlock* other_branch);
3034

    
3035
  void UpdateAdditionalLimit(InductionVariableLimitUpdate* update);
3036

    
3037
  HPhi* phi() { return phi_; }
3038
  HValue* base() { return base_; }
3039
  int32_t increment() { return increment_; }
3040
  HValue* limit() { return limit_; }
3041
  bool limit_included() { return limit_included_; }
3042
  HBasicBlock* limit_validity() { return limit_validity_; }
3043
  HBasicBlock* induction_exit_block() { return induction_exit_block_; }
3044
  HBasicBlock* induction_exit_target() { return induction_exit_target_; }
3045
  ChecksRelatedToLength* checks() { return checks_; }
3046
  HValue* additional_upper_limit() { return additional_upper_limit_; }
3047
  bool additional_upper_limit_is_included() {
3048
    return additional_upper_limit_is_included_;
3049
  }
3050
  HValue* additional_lower_limit() { return additional_lower_limit_; }
3051
  bool additional_lower_limit_is_included() {
3052
    return additional_lower_limit_is_included_;
3053
  }
3054

    
3055
  bool LowerLimitIsNonNegativeConstant() {
3056
    if (base()->IsInteger32Constant() && base()->GetInteger32Constant() >= 0) {
3057
      return true;
3058
    }
3059
    if (additional_lower_limit() != NULL &&
3060
        additional_lower_limit()->IsInteger32Constant() &&
3061
        additional_lower_limit()->GetInteger32Constant() >= 0) {
3062
      // Ignoring the corner case of !additional_lower_limit_is_included()
3063
      // is safe, handling it adds unneeded complexity.
3064
      return true;
3065
    }
3066
    return false;
3067
  }
3068

    
3069
  int32_t ComputeUpperLimit(int32_t and_mask, int32_t or_mask);
3070

    
3071
 private:
3072
  template <class T> void swap(T* a, T* b) {
3073
    T c(*a);
3074
    *a = *b;
3075
    *b = c;
3076
  }
3077

    
3078
  InductionVariableData(HPhi* phi, HValue* base, int32_t increment)
3079
      : phi_(phi), base_(IgnoreOsrValue(base)), increment_(increment),
3080
        limit_(NULL), limit_included_(false), limit_validity_(NULL),
3081
        induction_exit_block_(NULL), induction_exit_target_(NULL),
3082
        checks_(NULL),
3083
        additional_upper_limit_(NULL),
3084
        additional_upper_limit_is_included_(false),
3085
        additional_lower_limit_(NULL),
3086
        additional_lower_limit_is_included_(false) {}
3087

    
3088
  static int32_t ComputeIncrement(HPhi* phi, HValue* phi_operand);
3089

    
3090
  static HValue* IgnoreOsrValue(HValue* v);
3091
  static InductionVariableData* GetInductionVariableData(HValue* v);
3092

    
3093
  HPhi* phi_;
3094
  HValue* base_;
3095
  int32_t increment_;
3096
  HValue* limit_;
3097
  bool limit_included_;
3098
  HBasicBlock* limit_validity_;
3099
  HBasicBlock* induction_exit_block_;
3100
  HBasicBlock* induction_exit_target_;
3101
  ChecksRelatedToLength* checks_;
3102
  HValue* additional_upper_limit_;
3103
  bool additional_upper_limit_is_included_;
3104
  HValue* additional_lower_limit_;
3105
  bool additional_lower_limit_is_included_;
3106
};
3107

    
3108

    
3109
class HPhi V8_FINAL : public HValue {
3110
 public:
3111
  HPhi(int merged_index, Zone* zone)
3112
      : inputs_(2, zone),
3113
        merged_index_(merged_index),
3114
        phi_id_(-1),
3115
        induction_variable_data_(NULL) {
3116
    for (int i = 0; i < Representation::kNumRepresentations; i++) {
3117
      non_phi_uses_[i] = 0;
3118
      indirect_uses_[i] = 0;
3119
    }
3120
    ASSERT(merged_index >= 0 || merged_index == kInvalidMergedIndex);
3121
    SetFlag(kFlexibleRepresentation);
3122
    SetFlag(kAllowUndefinedAsNaN);
3123
  }
3124

    
3125
  virtual Representation RepresentationFromInputs() V8_OVERRIDE;
3126

    
3127
  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
3128
  virtual void InferRepresentation(
3129
      HInferRepresentationPhase* h_infer) V8_OVERRIDE;
3130
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3131
    return representation();
3132
  }
3133
  virtual Representation KnownOptimalRepresentation() V8_OVERRIDE {
3134
    return representation();
3135
  }
3136
  virtual HType CalculateInferredType() V8_OVERRIDE;
3137
  virtual int OperandCount() V8_OVERRIDE { return inputs_.length(); }
3138
  virtual HValue* OperandAt(int index) const V8_OVERRIDE {
3139
    return inputs_[index];
3140
  }
3141
  HValue* GetRedundantReplacement();
3142
  void AddInput(HValue* value);
3143
  bool HasRealUses();
3144

    
3145
  bool IsReceiver() const { return merged_index_ == 0; }
3146
  bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; }
3147

    
3148
  virtual int position() const V8_OVERRIDE;
3149

    
3150
  int merged_index() const { return merged_index_; }
3151

    
3152
  InductionVariableData* induction_variable_data() {
3153
    return induction_variable_data_;
3154
  }
3155
  bool IsInductionVariable() {
3156
    return induction_variable_data_ != NULL;
3157
  }
3158
  bool IsLimitedInductionVariable() {
3159
    return IsInductionVariable() &&
3160
        induction_variable_data_->limit() != NULL;
3161
  }
3162
  void DetectInductionVariable() {
3163
    ASSERT(induction_variable_data_ == NULL);
3164
    induction_variable_data_ = InductionVariableData::ExaminePhi(this);
3165
  }
3166

    
3167
  virtual void PrintTo(StringStream* stream) V8_OVERRIDE;
3168

    
3169
#ifdef DEBUG
3170
  virtual void Verify() V8_OVERRIDE;
3171
#endif
3172

    
3173
  void InitRealUses(int id);
3174
  void AddNonPhiUsesFrom(HPhi* other);
3175
  void AddIndirectUsesTo(int* use_count);
3176

    
3177
  int tagged_non_phi_uses() const {
3178
    return non_phi_uses_[Representation::kTagged];
3179
  }
3180
  int smi_non_phi_uses() const {
3181
    return non_phi_uses_[Representation::kSmi];
3182
  }
3183
  int int32_non_phi_uses() const {
3184
    return non_phi_uses_[Representation::kInteger32];
3185
  }
3186
  int double_non_phi_uses() const {
3187
    return non_phi_uses_[Representation::kDouble];
3188
  }
3189
  int tagged_indirect_uses() const {
3190
    return indirect_uses_[Representation::kTagged];
3191
  }
3192
  int smi_indirect_uses() const {
3193
    return indirect_uses_[Representation::kSmi];
3194
  }
3195
  int int32_indirect_uses() const {
3196
    return indirect_uses_[Representation::kInteger32];
3197
  }
3198
  int double_indirect_uses() const {
3199
    return indirect_uses_[Representation::kDouble];
3200
  }
3201
  int phi_id() { return phi_id_; }
3202

    
3203
  static HPhi* cast(HValue* value) {
3204
    ASSERT(value->IsPhi());
3205
    return reinterpret_cast<HPhi*>(value);
3206
  }
3207
  virtual Opcode opcode() const V8_OVERRIDE { return HValue::kPhi; }
3208

    
3209
  void SimplifyConstantInputs();
3210

    
3211
  // Marker value representing an invalid merge index.
3212
  static const int kInvalidMergedIndex = -1;
3213

    
3214
 protected:
3215
  virtual void DeleteFromGraph() V8_OVERRIDE;
3216
  virtual void InternalSetOperandAt(int index, HValue* value) V8_OVERRIDE {
3217
    inputs_[index] = value;
3218
  }
3219

    
3220
 private:
3221
  ZoneList<HValue*> inputs_;
3222
  int merged_index_;
3223

    
3224
  int non_phi_uses_[Representation::kNumRepresentations];
3225
  int indirect_uses_[Representation::kNumRepresentations];
3226
  int phi_id_;
3227
  InductionVariableData* induction_variable_data_;
3228

    
3229
  // TODO(titzer): we can't eliminate the receiver for generating backtraces
3230
  virtual bool IsDeletable() const V8_OVERRIDE { return !IsReceiver(); }
3231
};
3232

    
3233

    
3234
// Common base class for HArgumentsObject and HCapturedObject.
3235
class HDematerializedObject : public HInstruction {
3236
 public:
3237
  HDematerializedObject(int count, Zone* zone) : values_(count, zone) {}
3238

    
3239
  virtual int OperandCount() V8_FINAL V8_OVERRIDE { return values_.length(); }
3240
  virtual HValue* OperandAt(int index) const V8_FINAL V8_OVERRIDE {
3241
    return values_[index];
3242
  }
3243

    
3244
  virtual bool HasEscapingOperandAt(int index) V8_FINAL V8_OVERRIDE {
3245
    return false;
3246
  }
3247
  virtual Representation RequiredInputRepresentation(
3248
      int index) V8_FINAL V8_OVERRIDE {
3249
    return Representation::None();
3250
  }
3251

    
3252
 protected:
3253
  virtual void InternalSetOperandAt(int index,
3254
                                    HValue* value) V8_FINAL V8_OVERRIDE {
3255
    values_[index] = value;
3256
  }
3257

    
3258
  // List of values tracked by this marker.
3259
  ZoneList<HValue*> values_;
3260

    
3261
 private:
3262
  virtual bool IsDeletable() const V8_FINAL V8_OVERRIDE { return true; }
3263
};
3264

    
3265

    
3266
class HArgumentsObject V8_FINAL : public HDematerializedObject {
3267
 public:
3268
  static HArgumentsObject* New(Zone* zone, HValue* context, int count) {
3269
    return new(zone) HArgumentsObject(count, zone);
3270
  }
3271

    
3272
  // The values contain a list of all elements in the arguments object
3273
  // including the receiver object, which is skipped when materializing.
3274
  const ZoneList<HValue*>* arguments_values() const { return &values_; }
3275
  int arguments_count() const { return values_.length(); }
3276

    
3277
  void AddArgument(HValue* argument, Zone* zone) {
3278
    values_.Add(NULL, zone);  // Resize list.
3279
    SetOperandAt(values_.length() - 1, argument);
3280
  }
3281

    
3282
  DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
3283

    
3284
 private:
3285
  HArgumentsObject(int count, Zone* zone)
3286
      : HDematerializedObject(count, zone) {
3287
    set_representation(Representation::Tagged());
3288
    SetFlag(kIsArguments);
3289
  }
3290
};
3291

    
3292

    
3293
class HCapturedObject V8_FINAL : public HDematerializedObject {
3294
 public:
3295
  HCapturedObject(int length, int id, Zone* zone)
3296
      : HDematerializedObject(length, zone), capture_id_(id) {
3297
    set_representation(Representation::Tagged());
3298
    values_.AddBlock(NULL, length, zone);  // Resize list.
3299
  }
3300

    
3301
  // The values contain a list of all in-object properties inside the
3302
  // captured object and is index by field index. Properties in the
3303
  // properties or elements backing store are not tracked here.
3304
  const ZoneList<HValue*>* values() const { return &values_; }
3305
  int length() const { return values_.length(); }
3306
  int capture_id() const { return capture_id_; }
3307

    
3308
  // Shortcut for the map value of this captured object.
3309
  HValue* map_value() const { return values()->first(); }
3310

    
3311
  void ReuseSideEffectsFromStore(HInstruction* store) {
3312
    ASSERT(store->HasObservableSideEffects());
3313
    ASSERT(store->IsStoreNamedField());
3314
    gvn_flags_.Add(store->gvn_flags());
3315
  }
3316

    
3317
  // Replay effects of this instruction on the given environment.
3318
  void ReplayEnvironment(HEnvironment* env);
3319

    
3320
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3321

    
3322
  DECLARE_CONCRETE_INSTRUCTION(CapturedObject)
3323

    
3324
 private:
3325
  int capture_id_;
3326
};
3327

    
3328

    
3329
class HConstant V8_FINAL : public HTemplateInstruction<0> {
3330
 public:
3331
  DECLARE_INSTRUCTION_FACTORY_P1(HConstant, int32_t);
3332
  DECLARE_INSTRUCTION_FACTORY_P2(HConstant, int32_t, Representation);
3333
  DECLARE_INSTRUCTION_FACTORY_P1(HConstant, double);
3334
  DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Handle<Object>);
3335
  DECLARE_INSTRUCTION_FACTORY_P1(HConstant, ExternalReference);
3336

    
3337
  static HConstant* CreateAndInsertAfter(Zone* zone,
3338
                                         HValue* context,
3339
                                         int32_t value,
3340
                                         Representation representation,
3341
                                         HInstruction* instruction) {
3342
    HConstant* new_constant =
3343
        HConstant::New(zone, context, value, representation);
3344
    new_constant->InsertAfter(instruction);
3345
    return new_constant;
3346
  }
3347

    
3348
  static HConstant* CreateAndInsertBefore(Zone* zone,
3349
                                          HValue* context,
3350
                                          int32_t value,
3351
                                          Representation representation,
3352
                                          HInstruction* instruction) {
3353
    HConstant* new_constant =
3354
        HConstant::New(zone, context, value, representation);
3355
    new_constant->InsertBefore(instruction);
3356
    return new_constant;
3357
  }
3358

    
3359
  static HConstant* CreateAndInsertBefore(Zone* zone,
3360
                                          Unique<Object> unique,
3361
                                          bool is_not_in_new_space,
3362
                                          HInstruction* instruction) {
3363
    HConstant* new_constant = new(zone) HConstant(unique,
3364
        Representation::Tagged(), HType::Tagged(), false, is_not_in_new_space,
3365
        false, false);
3366
    new_constant->InsertBefore(instruction);
3367
    return new_constant;
3368
  }
3369

    
3370
  Handle<Object> handle(Isolate* isolate) {
3371
    if (object_.handle().is_null()) {
3372
      // Default arguments to is_not_in_new_space depend on this heap number
3373
      // to be tenured so that it's guaranteed not to be located in new space.
3374
      object_ = Unique<Object>::CreateUninitialized(
3375
          isolate->factory()->NewNumber(double_value_, TENURED));
3376
    }
3377
    AllowDeferredHandleDereference smi_check;
3378
    ASSERT(has_int32_value_ || !object_.handle()->IsSmi());
3379
    return object_.handle();
3380
  }
3381

    
3382
  bool HasMap(Handle<Map> map) {
3383
    Handle<Object> constant_object = handle(map->GetIsolate());
3384
    return constant_object->IsHeapObject() &&
3385
        Handle<HeapObject>::cast(constant_object)->map() == *map;
3386
  }
3387

    
3388
  bool IsSpecialDouble() const {
3389
    return has_double_value_ &&
3390
        (BitCast<int64_t>(double_value_) == BitCast<int64_t>(-0.0) ||
3391
         FixedDoubleArray::is_the_hole_nan(double_value_) ||
3392
         std::isnan(double_value_));
3393
  }
3394

    
3395
  bool NotInNewSpace() const {
3396
    return is_not_in_new_space_;
3397
  }
3398

    
3399
  bool ImmortalImmovable() const {
3400
    if (has_int32_value_) {
3401
      return false;
3402
    }
3403
    if (has_double_value_) {
3404
      if (IsSpecialDouble()) {
3405
        return true;
3406
      }
3407
      return false;
3408
    }
3409
    if (has_external_reference_value_) {
3410
      return false;
3411
    }
3412

    
3413
    ASSERT(!object_.handle().is_null());
3414
    Heap* heap = isolate()->heap();
3415
    ASSERT(!object_.IsKnownGlobal(heap->minus_zero_value()));
3416
    ASSERT(!object_.IsKnownGlobal(heap->nan_value()));
3417
    return
3418
        object_.IsKnownGlobal(heap->undefined_value()) ||
3419
        object_.IsKnownGlobal(heap->null_value()) ||
3420
        object_.IsKnownGlobal(heap->true_value()) ||
3421
        object_.IsKnownGlobal(heap->false_value()) ||
3422
        object_.IsKnownGlobal(heap->the_hole_value()) ||
3423
        object_.IsKnownGlobal(heap->empty_string()) ||
3424
        object_.IsKnownGlobal(heap->empty_fixed_array());
3425
  }
3426

    
3427
  bool IsCell() const {
3428
    return is_cell_;
3429
  }
3430

    
3431
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3432
    return Representation::None();
3433
  }
3434

    
3435
  virtual Representation KnownOptimalRepresentation() V8_OVERRIDE {
3436
    if (HasSmiValue() && SmiValuesAre31Bits()) return Representation::Smi();
3437
    if (HasInteger32Value()) return Representation::Integer32();
3438
    if (HasNumberValue()) return Representation::Double();
3439
    if (HasExternalReferenceValue()) return Representation::External();
3440
    return Representation::Tagged();
3441
  }
3442

    
3443
  virtual bool EmitAtUses() V8_OVERRIDE;
3444
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3445
  HConstant* CopyToRepresentation(Representation r, Zone* zone) const;
3446
  Maybe<HConstant*> CopyToTruncatedInt32(Zone* zone);
3447
  Maybe<HConstant*> CopyToTruncatedNumber(Zone* zone);
3448
  bool HasInteger32Value() const { return has_int32_value_; }
3449
  int32_t Integer32Value() const {
3450
    ASSERT(HasInteger32Value());
3451
    return int32_value_;
3452
  }
3453
  bool HasSmiValue() const { return has_smi_value_; }
3454
  bool HasDoubleValue() const { return has_double_value_; }
3455
  double DoubleValue() const {
3456
    ASSERT(HasDoubleValue());
3457
    return double_value_;
3458
  }
3459
  bool IsTheHole() const {
3460
    if (HasDoubleValue() && FixedDoubleArray::is_the_hole_nan(double_value_)) {
3461
      return true;
3462
    }
3463
    return object_.IsKnownGlobal(isolate()->heap()->the_hole_value());
3464
  }
3465
  bool HasNumberValue() const { return has_double_value_; }
3466
  int32_t NumberValueAsInteger32() const {
3467
    ASSERT(HasNumberValue());
3468
    // Irrespective of whether a numeric HConstant can be safely
3469
    // represented as an int32, we store the (in some cases lossy)
3470
    // representation of the number in int32_value_.
3471
    return int32_value_;
3472
  }
3473
  bool HasStringValue() const {
3474
    if (has_double_value_ || has_int32_value_) return false;
3475
    ASSERT(!object_.handle().is_null());
3476
    return type_.IsString();
3477
  }
3478
  Handle<String> StringValue() const {
3479
    ASSERT(HasStringValue());
3480
    return Handle<String>::cast(object_.handle());
3481
  }
3482
  bool HasInternalizedStringValue() const {
3483
    return HasStringValue() && is_internalized_string_;
3484
  }
3485

    
3486
  bool HasExternalReferenceValue() const {
3487
    return has_external_reference_value_;
3488
  }
3489
  ExternalReference ExternalReferenceValue() const {
3490
    return external_reference_value_;
3491
  }
3492

    
3493
  bool HasBooleanValue() const { return type_.IsBoolean(); }
3494
  bool BooleanValue() const { return boolean_value_; }
3495

    
3496
  virtual intptr_t Hashcode() V8_OVERRIDE {
3497
    if (has_int32_value_) {
3498
      return static_cast<intptr_t>(int32_value_);
3499
    } else if (has_double_value_) {
3500
      return static_cast<intptr_t>(BitCast<int64_t>(double_value_));
3501
    } else if (has_external_reference_value_) {
3502
      return reinterpret_cast<intptr_t>(external_reference_value_.address());
3503
    } else {
3504
      ASSERT(!object_.handle().is_null());
3505
      return object_.Hashcode();
3506
    }
3507
  }
3508

    
3509
  virtual void FinalizeUniqueness() V8_OVERRIDE {
3510
    if (!has_double_value_ && !has_external_reference_value_) {
3511
      ASSERT(!object_.handle().is_null());
3512
      object_ = Unique<Object>(object_.handle());
3513
    }
3514
  }
3515

    
3516
  Unique<Object> GetUnique() const {
3517
    return object_;
3518
  }
3519

    
3520
#ifdef DEBUG
3521
  virtual void Verify() V8_OVERRIDE { }
3522
#endif
3523

    
3524
  DECLARE_CONCRETE_INSTRUCTION(Constant)
3525

    
3526
 protected:
3527
  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
3528

    
3529
  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
3530
    HConstant* other_constant = HConstant::cast(other);
3531
    if (has_int32_value_) {
3532
      return other_constant->has_int32_value_ &&
3533
          int32_value_ == other_constant->int32_value_;
3534
    } else if (has_double_value_) {
3535
      return other_constant->has_double_value_ &&
3536
          BitCast<int64_t>(double_value_) ==
3537
          BitCast<int64_t>(other_constant->double_value_);
3538
    } else if (has_external_reference_value_) {
3539
      return other_constant->has_external_reference_value_ &&
3540
          external_reference_value_ ==
3541
          other_constant->external_reference_value_;
3542
    } else {
3543
      if (other_constant->has_int32_value_ ||
3544
          other_constant->has_double_value_ ||
3545
          other_constant->has_external_reference_value_) {
3546
        return false;
3547
      }
3548
      ASSERT(!object_.handle().is_null());
3549
      return other_constant->object_ == object_;
3550
    }
3551
  }
3552

    
3553
 private:
3554
  friend class HGraph;
3555
  HConstant(Handle<Object> handle, Representation r = Representation::None());
3556
  HConstant(int32_t value,
3557
            Representation r = Representation::None(),
3558
            bool is_not_in_new_space = true,
3559
            Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
3560
  HConstant(double value,
3561
            Representation r = Representation::None(),
3562
            bool is_not_in_new_space = true,
3563
            Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
3564
  HConstant(Unique<Object> unique,
3565
            Representation r,
3566
            HType type,
3567
            bool is_internalized_string,
3568
            bool is_not_in_new_space,
3569
            bool is_cell,
3570
            bool boolean_value);
3571

    
3572
  explicit HConstant(ExternalReference reference);
3573

    
3574
  void Initialize(Representation r);
3575

    
3576
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
3577

    
3578
  // If this is a numerical constant, object_ either points to the
3579
  // HeapObject the constant originated from or is null.  If the
3580
  // constant is non-numeric, object_ always points to a valid
3581
  // constant HeapObject.
3582
  Unique<Object> object_;
3583

    
3584
  // We store the HConstant in the most specific form safely possible.
3585
  // The two flags, has_int32_value_ and has_double_value_ tell us if
3586
  // int32_value_ and double_value_ hold valid, safe representations
3587
  // of the constant.  has_int32_value_ implies has_double_value_ but
3588
  // not the converse.
3589
  bool has_smi_value_ : 1;
3590
  bool has_int32_value_ : 1;
3591
  bool has_double_value_ : 1;
3592
  bool has_external_reference_value_ : 1;
3593
  bool is_internalized_string_ : 1;  // TODO(yangguo): make this part of HType.
3594
  bool is_not_in_new_space_ : 1;
3595
  bool is_cell_ : 1;
3596
  bool boolean_value_ : 1;
3597
  int32_t int32_value_;
3598
  double double_value_;
3599
  ExternalReference external_reference_value_;
3600
};
3601

    
3602

    
3603
class HBinaryOperation : public HTemplateInstruction<3> {
3604
 public:
3605
  HBinaryOperation(HValue* context, HValue* left, HValue* right,
3606
                   HType type = HType::Tagged())
3607
      : HTemplateInstruction<3>(type),
3608
        observed_output_representation_(Representation::None()) {
3609
    ASSERT(left != NULL && right != NULL);
3610
    SetOperandAt(0, context);
3611
    SetOperandAt(1, left);
3612
    SetOperandAt(2, right);
3613
    observed_input_representation_[0] = Representation::None();
3614
    observed_input_representation_[1] = Representation::None();
3615
  }
3616

    
3617
  HValue* context() const { return OperandAt(0); }
3618
  HValue* left() const { return OperandAt(1); }
3619
  HValue* right() const { return OperandAt(2); }
3620

    
3621
  // True if switching left and right operands likely generates better code.
3622
  bool AreOperandsBetterSwitched() {
3623
    if (!IsCommutative()) return false;
3624

    
3625
    // Constant operands are better off on the right, they can be inlined in
3626
    // many situations on most platforms.
3627
    if (left()->IsConstant()) return true;
3628
    if (right()->IsConstant()) return false;
3629

    
3630
    // Otherwise, if there is only one use of the right operand, it would be
3631
    // better off on the left for platforms that only have 2-arg arithmetic
3632
    // ops (e.g ia32, x64) that clobber the left operand.
3633
    return right()->UseCount() == 1;
3634
  }
3635

    
3636
  HValue* BetterLeftOperand() {
3637
    return AreOperandsBetterSwitched() ? right() : left();
3638
  }
3639

    
3640
  HValue* BetterRightOperand() {
3641
    return AreOperandsBetterSwitched() ? left() : right();
3642
  }
3643

    
3644
  void set_observed_input_representation(int index, Representation rep) {
3645
    ASSERT(index >= 1 && index <= 2);
3646
    observed_input_representation_[index - 1] = rep;
3647
  }
3648

    
3649
  virtual void initialize_output_representation(Representation observed) {
3650
    observed_output_representation_ = observed;
3651
  }
3652

    
3653
  virtual Representation observed_input_representation(int index) V8_OVERRIDE {
3654
    if (index == 0) return Representation::Tagged();
3655
    return observed_input_representation_[index - 1];
3656
  }
3657

    
3658
  virtual void UpdateRepresentation(Representation new_rep,
3659
                                    HInferRepresentationPhase* h_infer,
3660
                                    const char* reason) V8_OVERRIDE {
3661
    Representation rep = !FLAG_smi_binop && new_rep.IsSmi()
3662
        ? Representation::Integer32() : new_rep;
3663
    HValue::UpdateRepresentation(rep, h_infer, reason);
3664
  }
3665

    
3666
  virtual void InferRepresentation(
3667
      HInferRepresentationPhase* h_infer) V8_OVERRIDE;
3668
  virtual Representation RepresentationFromInputs() V8_OVERRIDE;
3669
  Representation RepresentationFromOutput();
3670
  virtual void AssumeRepresentation(Representation r) V8_OVERRIDE;
3671

    
3672
  virtual bool IsCommutative() const { return false; }
3673

    
3674
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3675

    
3676
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3677
    if (index == 0) return Representation::Tagged();
3678
    return representation();
3679
  }
3680

    
3681
  DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation)
3682

    
3683
 private:
3684
  bool IgnoreObservedOutputRepresentation(Representation current_rep);
3685

    
3686
  Representation observed_input_representation_[2];
3687
  Representation observed_output_representation_;
3688
};
3689

    
3690

    
3691
class HWrapReceiver V8_FINAL : public HTemplateInstruction<2> {
3692
 public:
3693
  DECLARE_INSTRUCTION_FACTORY_P2(HWrapReceiver, HValue*, HValue*);
3694

    
3695
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3696
    return Representation::Tagged();
3697
  }
3698

    
3699
  HValue* receiver() { return OperandAt(0); }
3700
  HValue* function() { return OperandAt(1); }
3701

    
3702
  virtual HValue* Canonicalize() V8_OVERRIDE;
3703

    
3704
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3705

    
3706
  DECLARE_CONCRETE_INSTRUCTION(WrapReceiver)
3707

    
3708
 private:
3709
  HWrapReceiver(HValue* receiver, HValue* function) {
3710
    set_representation(Representation::Tagged());
3711
    SetOperandAt(0, receiver);
3712
    SetOperandAt(1, function);
3713
  }
3714
};
3715

    
3716

    
3717
class HApplyArguments V8_FINAL : public HTemplateInstruction<4> {
3718
 public:
3719
  DECLARE_INSTRUCTION_FACTORY_P4(HApplyArguments, HValue*, HValue*, HValue*,
3720
                                 HValue*);
3721

    
3722
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3723
    // The length is untagged, all other inputs are tagged.
3724
    return (index == 2)
3725
        ? Representation::Integer32()
3726
        : Representation::Tagged();
3727
  }
3728

    
3729
  HValue* function() { return OperandAt(0); }
3730
  HValue* receiver() { return OperandAt(1); }
3731
  HValue* length() { return OperandAt(2); }
3732
  HValue* elements() { return OperandAt(3); }
3733

    
3734
  DECLARE_CONCRETE_INSTRUCTION(ApplyArguments)
3735

    
3736
 private:
3737
  HApplyArguments(HValue* function,
3738
                  HValue* receiver,
3739
                  HValue* length,
3740
                  HValue* elements) {
3741
    set_representation(Representation::Tagged());
3742
    SetOperandAt(0, function);
3743
    SetOperandAt(1, receiver);
3744
    SetOperandAt(2, length);
3745
    SetOperandAt(3, elements);
3746
    SetAllSideEffects();
3747
  }
3748
};
3749

    
3750

    
3751
class HArgumentsElements V8_FINAL : public HTemplateInstruction<0> {
3752
 public:
3753
  DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsElements, bool);
3754

    
3755
  DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements)
3756

    
3757
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3758
    return Representation::None();
3759
  }
3760

    
3761
  bool from_inlined() const { return from_inlined_; }
3762

    
3763
 protected:
3764
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3765

    
3766
 private:
3767
  explicit HArgumentsElements(bool from_inlined) : from_inlined_(from_inlined) {
3768
    // The value produced by this instruction is a pointer into the stack
3769
    // that looks as if it was a smi because of alignment.
3770
    set_representation(Representation::Tagged());
3771
    SetFlag(kUseGVN);
3772
  }
3773

    
3774
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
3775

    
3776
  bool from_inlined_;
3777
};
3778

    
3779

    
3780
class HArgumentsLength V8_FINAL : public HUnaryOperation {
3781
 public:
3782
  DECLARE_INSTRUCTION_FACTORY_P1(HArgumentsLength, HValue*);
3783

    
3784
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3785
    return Representation::Tagged();
3786
  }
3787

    
3788
  DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength)
3789

    
3790
 protected:
3791
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3792

    
3793
 private:
3794
  explicit HArgumentsLength(HValue* value) : HUnaryOperation(value) {
3795
    set_representation(Representation::Integer32());
3796
    SetFlag(kUseGVN);
3797
  }
3798

    
3799
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
3800
};
3801

    
3802

    
3803
class HAccessArgumentsAt V8_FINAL : public HTemplateInstruction<3> {
3804
 public:
3805
  DECLARE_INSTRUCTION_FACTORY_P3(HAccessArgumentsAt, HValue*, HValue*, HValue*);
3806

    
3807
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3808

    
3809
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3810
    // The arguments elements is considered tagged.
3811
    return index == 0
3812
        ? Representation::Tagged()
3813
        : Representation::Integer32();
3814
  }
3815

    
3816
  HValue* arguments() { return OperandAt(0); }
3817
  HValue* length() { return OperandAt(1); }
3818
  HValue* index() { return OperandAt(2); }
3819

    
3820
  DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt)
3821

    
3822
 private:
3823
  HAccessArgumentsAt(HValue* arguments, HValue* length, HValue* index) {
3824
    set_representation(Representation::Tagged());
3825
    SetFlag(kUseGVN);
3826
    SetOperandAt(0, arguments);
3827
    SetOperandAt(1, length);
3828
    SetOperandAt(2, index);
3829
  }
3830

    
3831
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3832
};
3833

    
3834

    
3835
class HBoundsCheckBaseIndexInformation;
3836

    
3837

    
3838
class HBoundsCheck V8_FINAL : public HTemplateInstruction<2> {
3839
 public:
3840
  DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*);
3841

    
3842
  bool skip_check() const { return skip_check_; }
3843
  void set_skip_check() { skip_check_ = true; }
3844

    
3845
  HValue* base() { return base_; }
3846
  int offset() { return offset_; }
3847
  int scale() { return scale_; }
3848

    
3849
  void ApplyIndexChange();
3850
  bool DetectCompoundIndex() {
3851
    ASSERT(base() == NULL);
3852

    
3853
    DecompositionResult decomposition;
3854
    if (index()->TryDecompose(&decomposition)) {
3855
      base_ = decomposition.base();
3856
      offset_ = decomposition.offset();
3857
      scale_ = decomposition.scale();
3858
      return true;
3859
    } else {
3860
      base_ = index();
3861
      offset_ = 0;
3862
      scale_ = 0;
3863
      return false;
3864
    }
3865
  }
3866

    
3867
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3868
    return representation();
3869
  }
3870

    
3871
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3872
  virtual void InferRepresentation(
3873
      HInferRepresentationPhase* h_infer) V8_OVERRIDE;
3874

    
3875
  HValue* index() { return OperandAt(0); }
3876
  HValue* length() { return OperandAt(1); }
3877
  bool allow_equality() { return allow_equality_; }
3878
  void set_allow_equality(bool v) { allow_equality_ = v; }
3879

    
3880
  virtual int RedefinedOperandIndex() V8_OVERRIDE { return 0; }
3881
  virtual bool IsPurelyInformativeDefinition() V8_OVERRIDE {
3882
    return skip_check();
3883
  }
3884

    
3885
  DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
3886

    
3887
 protected:
3888
  friend class HBoundsCheckBaseIndexInformation;
3889

    
3890
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
3891
  bool skip_check_;
3892
  HValue* base_;
3893
  int offset_;
3894
  int scale_;
3895
  bool allow_equality_;
3896

    
3897
 private:
3898
  // Normally HBoundsCheck should be created using the
3899
  // HGraphBuilder::AddBoundsCheck() helper.
3900
  // However when building stubs, where we know that the arguments are Int32,
3901
  // it makes sense to invoke this constructor directly.
3902
  HBoundsCheck(HValue* index, HValue* length)
3903
    : skip_check_(false),
3904
      base_(NULL), offset_(0), scale_(0),
3905
      allow_equality_(false) {
3906
    SetOperandAt(0, index);
3907
    SetOperandAt(1, length);
3908
    SetFlag(kFlexibleRepresentation);
3909
    SetFlag(kUseGVN);
3910
  }
3911

    
3912
  virtual bool IsDeletable() const V8_OVERRIDE {
3913
    return skip_check() && !FLAG_debug_code;
3914
  }
3915
};
3916

    
3917

    
3918
class HBoundsCheckBaseIndexInformation V8_FINAL
3919
    : public HTemplateInstruction<2> {
3920
 public:
3921
  explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) {
3922
    DecompositionResult decomposition;
3923
    if (check->index()->TryDecompose(&decomposition)) {
3924
      SetOperandAt(0, decomposition.base());
3925
      SetOperandAt(1, check);
3926
    } else {
3927
      UNREACHABLE();
3928
    }
3929
  }
3930

    
3931
  HValue* base_index() { return OperandAt(0); }
3932
  HBoundsCheck* bounds_check() { return HBoundsCheck::cast(OperandAt(1)); }
3933

    
3934
  DECLARE_CONCRETE_INSTRUCTION(BoundsCheckBaseIndexInformation)
3935

    
3936
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
3937
    return representation();
3938
  }
3939

    
3940
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
3941

    
3942
  virtual int RedefinedOperandIndex() V8_OVERRIDE { return 0; }
3943
  virtual bool IsPurelyInformativeDefinition() V8_OVERRIDE { return true; }
3944
};
3945

    
3946

    
3947
class HBitwiseBinaryOperation : public HBinaryOperation {
3948
 public:
3949
  HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right,
3950
                          HType type = HType::Tagged())
3951
      : HBinaryOperation(context, left, right, type) {
3952
    SetFlag(kFlexibleRepresentation);
3953
    SetFlag(kTruncatingToInt32);
3954
    SetFlag(kAllowUndefinedAsNaN);
3955
    SetAllSideEffects();
3956
  }
3957

    
3958
  virtual void RepresentationChanged(Representation to) V8_OVERRIDE {
3959
    if (to.IsTagged()) SetGVNFlag(kChangesNewSpacePromotion);
3960
    if (to.IsTagged() &&
3961
        (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
3962
      SetAllSideEffects();
3963
      ClearFlag(kUseGVN);
3964
    } else {
3965
      ClearAllSideEffects();
3966
      SetFlag(kUseGVN);
3967
    }
3968
  }
3969

    
3970
  virtual void UpdateRepresentation(Representation new_rep,
3971
                                    HInferRepresentationPhase* h_infer,
3972
                                    const char* reason) V8_OVERRIDE {
3973
    // We only generate either int32 or generic tagged bitwise operations.
3974
    if (new_rep.IsDouble()) new_rep = Representation::Integer32();
3975
    HBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
3976
  }
3977

    
3978
  virtual Representation observed_input_representation(int index) V8_OVERRIDE {
3979
    Representation r = HBinaryOperation::observed_input_representation(index);
3980
    if (r.IsDouble()) return Representation::Integer32();
3981
    return r;
3982
  }
3983

    
3984
  virtual void initialize_output_representation(Representation observed) {
3985
    if (observed.IsDouble()) observed = Representation::Integer32();
3986
    HBinaryOperation::initialize_output_representation(observed);
3987
  }
3988

    
3989
  DECLARE_ABSTRACT_INSTRUCTION(BitwiseBinaryOperation)
3990

    
3991
 private:
3992
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
3993
};
3994

    
3995

    
3996
class HMathFloorOfDiv V8_FINAL : public HBinaryOperation {
3997
 public:
3998
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HMathFloorOfDiv,
3999
                                              HValue*,
4000
                                              HValue*);
4001

    
4002
  virtual HValue* EnsureAndPropagateNotMinusZero(
4003
      BitVector* visited) V8_OVERRIDE;
4004

    
4005
  DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv)
4006

    
4007
 protected:
4008
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4009

    
4010
 private:
4011
  HMathFloorOfDiv(HValue* context, HValue* left, HValue* right)
4012
      : HBinaryOperation(context, left, right) {
4013
    set_representation(Representation::Integer32());
4014
    SetFlag(kUseGVN);
4015
    SetFlag(kCanOverflow);
4016
    if (!right->IsConstant()) {
4017
      SetFlag(kCanBeDivByZero);
4018
    }
4019
    SetFlag(kAllowUndefinedAsNaN);
4020
  }
4021

    
4022
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
4023
};
4024

    
4025

    
4026
class HArithmeticBinaryOperation : public HBinaryOperation {
4027
 public:
4028
  HArithmeticBinaryOperation(HValue* context, HValue* left, HValue* right)
4029
      : HBinaryOperation(context, left, right, HType::TaggedNumber()) {
4030
    SetAllSideEffects();
4031
    SetFlag(kFlexibleRepresentation);
4032
    SetFlag(kAllowUndefinedAsNaN);
4033
  }
4034

    
4035
  virtual void RepresentationChanged(Representation to) V8_OVERRIDE {
4036
    if (to.IsTagged()) SetGVNFlag(kChangesNewSpacePromotion);
4037
    if (to.IsTagged() &&
4038
        (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
4039
      SetAllSideEffects();
4040
      ClearFlag(kUseGVN);
4041
    } else {
4042
      ClearAllSideEffects();
4043
      SetFlag(kUseGVN);
4044
    }
4045
  }
4046

    
4047
  DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)
4048
 private:
4049
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
4050
};
4051

    
4052

    
4053
class HCompareGeneric V8_FINAL : public HBinaryOperation {
4054
 public:
4055
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HCompareGeneric, HValue*,
4056
                                              HValue*, Token::Value);
4057

    
4058
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4059
    return index == 0
4060
        ? Representation::Tagged()
4061
        : representation();
4062
  }
4063

    
4064
  Token::Value token() const { return token_; }
4065
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4066

    
4067
  DECLARE_CONCRETE_INSTRUCTION(CompareGeneric)
4068

    
4069
 private:
4070
  HCompareGeneric(HValue* context,
4071
                  HValue* left,
4072
                  HValue* right,
4073
                  Token::Value token)
4074
      : HBinaryOperation(context, left, right, HType::Boolean()),
4075
        token_(token) {
4076
    ASSERT(Token::IsCompareOp(token));
4077
    set_representation(Representation::Tagged());
4078
    SetAllSideEffects();
4079
  }
4080

    
4081
  Token::Value token_;
4082
};
4083

    
4084

    
4085
class HCompareNumericAndBranch : public HTemplateControlInstruction<2, 2> {
4086
 public:
4087
  DECLARE_INSTRUCTION_FACTORY_P3(HCompareNumericAndBranch,
4088
                                 HValue*, HValue*, Token::Value);
4089
  DECLARE_INSTRUCTION_FACTORY_P5(HCompareNumericAndBranch,
4090
                                 HValue*, HValue*, Token::Value,
4091
                                 HBasicBlock*, HBasicBlock*);
4092

    
4093
  HValue* left() { return OperandAt(0); }
4094
  HValue* right() { return OperandAt(1); }
4095
  Token::Value token() const { return token_; }
4096

    
4097
  void set_observed_input_representation(Representation left,
4098
                                         Representation right) {
4099
      observed_input_representation_[0] = left;
4100
      observed_input_representation_[1] = right;
4101
  }
4102

    
4103
  virtual void InferRepresentation(
4104
      HInferRepresentationPhase* h_infer) V8_OVERRIDE;
4105

    
4106
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4107
    return representation();
4108
  }
4109
  virtual Representation observed_input_representation(int index) V8_OVERRIDE {
4110
    return observed_input_representation_[index];
4111
  }
4112
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4113

    
4114
  DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)
4115

    
4116
 private:
4117
  HCompareNumericAndBranch(HValue* left,
4118
                           HValue* right,
4119
                           Token::Value token,
4120
                           HBasicBlock* true_target = NULL,
4121
                           HBasicBlock* false_target = NULL)
4122
      : token_(token) {
4123
    SetFlag(kFlexibleRepresentation);
4124
    ASSERT(Token::IsCompareOp(token));
4125
    SetOperandAt(0, left);
4126
    SetOperandAt(1, right);
4127
    SetSuccessorAt(0, true_target);
4128
    SetSuccessorAt(1, false_target);
4129
  }
4130

    
4131
  Representation observed_input_representation_[2];
4132
  Token::Value token_;
4133
};
4134

    
4135

    
4136
class HCompareHoleAndBranch V8_FINAL : public HUnaryControlInstruction {
4137
 public:
4138
  DECLARE_INSTRUCTION_FACTORY_P1(HCompareHoleAndBranch, HValue*);
4139
  DECLARE_INSTRUCTION_FACTORY_P3(HCompareHoleAndBranch, HValue*,
4140
                                 HBasicBlock*, HBasicBlock*);
4141

    
4142
  virtual void InferRepresentation(
4143
      HInferRepresentationPhase* h_infer) V8_OVERRIDE;
4144

    
4145
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4146
    return representation();
4147
  }
4148

    
4149
  DECLARE_CONCRETE_INSTRUCTION(CompareHoleAndBranch)
4150

    
4151
 private:
4152
  HCompareHoleAndBranch(HValue* value,
4153
                        HBasicBlock* true_target = NULL,
4154
                        HBasicBlock* false_target = NULL)
4155
      : HUnaryControlInstruction(value, true_target, false_target) {
4156
    SetFlag(kFlexibleRepresentation);
4157
    SetFlag(kAllowUndefinedAsNaN);
4158
  }
4159
};
4160

    
4161

    
4162
class HCompareObjectEqAndBranch : public HTemplateControlInstruction<2, 2> {
4163
 public:
4164
  HCompareObjectEqAndBranch(HValue* left,
4165
                            HValue* right,
4166
                            HBasicBlock* true_target = NULL,
4167
                            HBasicBlock* false_target = NULL) {
4168
    // TODO(danno): make this private when the IfBuilder properly constructs
4169
    // control flow instructions.
4170
    ASSERT(!left->IsConstant() ||
4171
           (!HConstant::cast(left)->HasInteger32Value() ||
4172
            HConstant::cast(left)->HasSmiValue()));
4173
    ASSERT(!right->IsConstant() ||
4174
           (!HConstant::cast(right)->HasInteger32Value() ||
4175
            HConstant::cast(right)->HasSmiValue()));
4176
    SetOperandAt(0, left);
4177
    SetOperandAt(1, right);
4178
    SetSuccessorAt(0, true_target);
4179
    SetSuccessorAt(1, false_target);
4180
  }
4181

    
4182
  DECLARE_INSTRUCTION_FACTORY_P2(HCompareObjectEqAndBranch, HValue*, HValue*);
4183
  DECLARE_INSTRUCTION_FACTORY_P4(HCompareObjectEqAndBranch, HValue*, HValue*,
4184
                                 HBasicBlock*, HBasicBlock*);
4185

    
4186
  virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
4187

    
4188
  HValue* left() { return OperandAt(0); }
4189
  HValue* right() { return OperandAt(1); }
4190

    
4191
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4192

    
4193
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4194
    return Representation::Tagged();
4195
  }
4196

    
4197
  virtual Representation observed_input_representation(int index) V8_OVERRIDE {
4198
    return Representation::Tagged();
4199
  }
4200

    
4201
  DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)
4202
};
4203

    
4204

    
4205
class HIsObjectAndBranch V8_FINAL : public HUnaryControlInstruction {
4206
 public:
4207
  DECLARE_INSTRUCTION_FACTORY_P1(HIsObjectAndBranch, HValue*);
4208
  DECLARE_INSTRUCTION_FACTORY_P3(HIsObjectAndBranch, HValue*,
4209
                                 HBasicBlock*, HBasicBlock*);
4210

    
4211
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4212
    return Representation::Tagged();
4213
  }
4214

    
4215
  DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch)
4216

    
4217
 private:
4218
  HIsObjectAndBranch(HValue* value,
4219
                     HBasicBlock* true_target = NULL,
4220
                     HBasicBlock* false_target = NULL)
4221
    : HUnaryControlInstruction(value, true_target, false_target) {}
4222
};
4223

    
4224

    
4225
class HIsStringAndBranch V8_FINAL : public HUnaryControlInstruction {
4226
 public:
4227
  DECLARE_INSTRUCTION_FACTORY_P1(HIsStringAndBranch, HValue*);
4228
  DECLARE_INSTRUCTION_FACTORY_P3(HIsStringAndBranch, HValue*,
4229
                                 HBasicBlock*, HBasicBlock*);
4230

    
4231
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4232
    return Representation::Tagged();
4233
  }
4234

    
4235
  DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
4236

    
4237
 private:
4238
  HIsStringAndBranch(HValue* value,
4239
                     HBasicBlock* true_target = NULL,
4240
                     HBasicBlock* false_target = NULL)
4241
    : HUnaryControlInstruction(value, true_target, false_target) {}
4242
};
4243

    
4244

    
4245
class HIsSmiAndBranch V8_FINAL : public HUnaryControlInstruction {
4246
 public:
4247
  DECLARE_INSTRUCTION_FACTORY_P1(HIsSmiAndBranch, HValue*);
4248
  DECLARE_INSTRUCTION_FACTORY_P3(HIsSmiAndBranch, HValue*,
4249
                                 HBasicBlock*, HBasicBlock*);
4250

    
4251
  DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch)
4252

    
4253
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4254
    return Representation::Tagged();
4255
  }
4256

    
4257
 protected:
4258
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4259

    
4260
 private:
4261
  HIsSmiAndBranch(HValue* value,
4262
                  HBasicBlock* true_target = NULL,
4263
                  HBasicBlock* false_target = NULL)
4264
      : HUnaryControlInstruction(value, true_target, false_target) {}
4265
};
4266

    
4267

    
4268
class HIsUndetectableAndBranch V8_FINAL : public HUnaryControlInstruction {
4269
 public:
4270
  DECLARE_INSTRUCTION_FACTORY_P1(HIsUndetectableAndBranch, HValue*);
4271
  DECLARE_INSTRUCTION_FACTORY_P3(HIsUndetectableAndBranch, HValue*,
4272
                                 HBasicBlock*, HBasicBlock*);
4273

    
4274
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4275
    return Representation::Tagged();
4276
  }
4277

    
4278
  DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch)
4279

    
4280
 private:
4281
  HIsUndetectableAndBranch(HValue* value,
4282
                           HBasicBlock* true_target = NULL,
4283
                           HBasicBlock* false_target = NULL)
4284
      : HUnaryControlInstruction(value, true_target, false_target) {}
4285
};
4286

    
4287

    
4288
class HStringCompareAndBranch : public HTemplateControlInstruction<2, 3> {
4289
 public:
4290
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HStringCompareAndBranch,
4291
                                              HValue*,
4292
                                              HValue*,
4293
                                              Token::Value);
4294

    
4295
  HValue* context() { return OperandAt(0); }
4296
  HValue* left() { return OperandAt(1); }
4297
  HValue* right() { return OperandAt(2); }
4298
  Token::Value token() const { return token_; }
4299

    
4300
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4301

    
4302
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4303
    return Representation::Tagged();
4304
  }
4305

    
4306
  Representation GetInputRepresentation() const {
4307
    return Representation::Tagged();
4308
  }
4309

    
4310
  DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch)
4311

    
4312
 private:
4313
  HStringCompareAndBranch(HValue* context,
4314
                          HValue* left,
4315
                          HValue* right,
4316
                          Token::Value token)
4317
      : token_(token) {
4318
    ASSERT(Token::IsCompareOp(token));
4319
    SetOperandAt(0, context);
4320
    SetOperandAt(1, left);
4321
    SetOperandAt(2, right);
4322
    set_representation(Representation::Tagged());
4323
    SetGVNFlag(kChangesNewSpacePromotion);
4324
  }
4325

    
4326
  Token::Value token_;
4327
};
4328

    
4329

    
4330
class HIsConstructCallAndBranch : public HTemplateControlInstruction<2, 0> {
4331
 public:
4332
  DECLARE_INSTRUCTION_FACTORY_P0(HIsConstructCallAndBranch);
4333

    
4334
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4335
    return Representation::None();
4336
  }
4337

    
4338
  DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch)
4339
 private:
4340
  HIsConstructCallAndBranch() {}
4341
};
4342

    
4343

    
4344
class HHasInstanceTypeAndBranch V8_FINAL : public HUnaryControlInstruction {
4345
 public:
4346
  DECLARE_INSTRUCTION_FACTORY_P2(
4347
      HHasInstanceTypeAndBranch, HValue*, InstanceType);
4348
  DECLARE_INSTRUCTION_FACTORY_P3(
4349
      HHasInstanceTypeAndBranch, HValue*, InstanceType, InstanceType);
4350

    
4351
  InstanceType from() { return from_; }
4352
  InstanceType to() { return to_; }
4353

    
4354
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4355

    
4356
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4357
    return Representation::Tagged();
4358
  }
4359

    
4360
  DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch)
4361

    
4362
 private:
4363
  HHasInstanceTypeAndBranch(HValue* value, InstanceType type)
4364
      : HUnaryControlInstruction(value, NULL, NULL), from_(type), to_(type) { }
4365
  HHasInstanceTypeAndBranch(HValue* value, InstanceType from, InstanceType to)
4366
      : HUnaryControlInstruction(value, NULL, NULL), from_(from), to_(to) {
4367
    ASSERT(to == LAST_TYPE);  // Others not implemented yet in backend.
4368
  }
4369

    
4370
  InstanceType from_;
4371
  InstanceType to_;  // Inclusive range, not all combinations work.
4372
};
4373

    
4374

    
4375
class HHasCachedArrayIndexAndBranch V8_FINAL : public HUnaryControlInstruction {
4376
 public:
4377
  DECLARE_INSTRUCTION_FACTORY_P1(HHasCachedArrayIndexAndBranch, HValue*);
4378

    
4379
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4380
    return Representation::Tagged();
4381
  }
4382

    
4383
  DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch)
4384
 private:
4385
  explicit HHasCachedArrayIndexAndBranch(HValue* value)
4386
      : HUnaryControlInstruction(value, NULL, NULL) { }
4387
};
4388

    
4389

    
4390
class HGetCachedArrayIndex V8_FINAL : public HUnaryOperation {
4391
 public:
4392
  DECLARE_INSTRUCTION_FACTORY_P1(HGetCachedArrayIndex, HValue*);
4393

    
4394
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4395
    return Representation::Tagged();
4396
  }
4397

    
4398
  DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex)
4399

    
4400
 protected:
4401
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4402

    
4403
 private:
4404
  explicit HGetCachedArrayIndex(HValue* value) : HUnaryOperation(value) {
4405
    set_representation(Representation::Tagged());
4406
    SetFlag(kUseGVN);
4407
  }
4408

    
4409
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
4410
};
4411

    
4412

    
4413
class HClassOfTestAndBranch V8_FINAL : public HUnaryControlInstruction {
4414
 public:
4415
  DECLARE_INSTRUCTION_FACTORY_P2(HClassOfTestAndBranch, HValue*,
4416
                                 Handle<String>);
4417

    
4418
  DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch)
4419

    
4420
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4421
    return Representation::Tagged();
4422
  }
4423

    
4424
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4425

    
4426
  Handle<String> class_name() const { return class_name_; }
4427

    
4428
 private:
4429
  HClassOfTestAndBranch(HValue* value, Handle<String> class_name)
4430
      : HUnaryControlInstruction(value, NULL, NULL),
4431
        class_name_(class_name) { }
4432

    
4433
  Handle<String> class_name_;
4434
};
4435

    
4436

    
4437
class HTypeofIsAndBranch V8_FINAL : public HUnaryControlInstruction {
4438
 public:
4439
  DECLARE_INSTRUCTION_FACTORY_P2(HTypeofIsAndBranch, HValue*, Handle<String>);
4440

    
4441
  Handle<String> type_literal() { return type_literal_; }
4442
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4443

    
4444
  DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch)
4445

    
4446
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4447
    return Representation::Tagged();
4448
  }
4449

    
4450
 private:
4451
  HTypeofIsAndBranch(HValue* value, Handle<String> type_literal)
4452
      : HUnaryControlInstruction(value, NULL, NULL),
4453
        type_literal_(type_literal) { }
4454

    
4455
  Handle<String> type_literal_;
4456
};
4457

    
4458

    
4459
class HInstanceOf V8_FINAL : public HBinaryOperation {
4460
 public:
4461
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInstanceOf, HValue*, HValue*);
4462

    
4463
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4464
    return Representation::Tagged();
4465
  }
4466

    
4467
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4468

    
4469
  DECLARE_CONCRETE_INSTRUCTION(InstanceOf)
4470

    
4471
 private:
4472
  HInstanceOf(HValue* context, HValue* left, HValue* right)
4473
      : HBinaryOperation(context, left, right, HType::Boolean()) {
4474
    set_representation(Representation::Tagged());
4475
    SetAllSideEffects();
4476
  }
4477
};
4478

    
4479

    
4480
class HInstanceOfKnownGlobal V8_FINAL : public HTemplateInstruction<2> {
4481
 public:
4482
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInstanceOfKnownGlobal,
4483
                                              HValue*,
4484
                                              Handle<JSFunction>);
4485

    
4486
  HValue* context() { return OperandAt(0); }
4487
  HValue* left() { return OperandAt(1); }
4488
  Handle<JSFunction> function() { return function_; }
4489

    
4490
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4491
    return Representation::Tagged();
4492
  }
4493

    
4494
  DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal)
4495

    
4496
 private:
4497
  HInstanceOfKnownGlobal(HValue* context,
4498
                         HValue* left,
4499
                         Handle<JSFunction> right)
4500
      : HTemplateInstruction<2>(HType::Boolean()), function_(right) {
4501
    SetOperandAt(0, context);
4502
    SetOperandAt(1, left);
4503
    set_representation(Representation::Tagged());
4504
    SetAllSideEffects();
4505
  }
4506

    
4507
  Handle<JSFunction> function_;
4508
};
4509

    
4510

    
4511
class HPower V8_FINAL : public HTemplateInstruction<2> {
4512
 public:
4513
  static HInstruction* New(Zone* zone,
4514
                           HValue* context,
4515
                           HValue* left,
4516
                           HValue* right);
4517

    
4518
  HValue* left() { return OperandAt(0); }
4519
  HValue* right() const { return OperandAt(1); }
4520

    
4521
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4522
    return index == 0
4523
      ? Representation::Double()
4524
      : Representation::None();
4525
  }
4526
  virtual Representation observed_input_representation(int index) V8_OVERRIDE {
4527
    return RequiredInputRepresentation(index);
4528
  }
4529

    
4530
  DECLARE_CONCRETE_INSTRUCTION(Power)
4531

    
4532
 protected:
4533
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4534

    
4535
 private:
4536
  HPower(HValue* left, HValue* right) {
4537
    SetOperandAt(0, left);
4538
    SetOperandAt(1, right);
4539
    set_representation(Representation::Double());
4540
    SetFlag(kUseGVN);
4541
    SetGVNFlag(kChangesNewSpacePromotion);
4542
  }
4543

    
4544
  virtual bool IsDeletable() const V8_OVERRIDE {
4545
    return !right()->representation().IsTagged();
4546
  }
4547
};
4548

    
4549

    
4550
class HRandom V8_FINAL : public HTemplateInstruction<1> {
4551
 public:
4552
  DECLARE_INSTRUCTION_FACTORY_P1(HRandom, HValue*);
4553

    
4554
  HValue* global_object() { return OperandAt(0); }
4555

    
4556
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
4557
    return Representation::Tagged();
4558
  }
4559

    
4560
  DECLARE_CONCRETE_INSTRUCTION(Random)
4561

    
4562
 private:
4563
  explicit HRandom(HValue* global_object) {
4564
    SetOperandAt(0, global_object);
4565
    set_representation(Representation::Double());
4566
  }
4567

    
4568
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
4569
};
4570

    
4571

    
4572
class HAdd V8_FINAL : public HArithmeticBinaryOperation {
4573
 public:
4574
  static HInstruction* New(Zone* zone,
4575
                           HValue* context,
4576
                           HValue* left,
4577
                           HValue* right);
4578

    
4579
  // Add is only commutative if two integer values are added and not if two
4580
  // tagged values are added (because it might be a String concatenation).
4581
  virtual bool IsCommutative() const V8_OVERRIDE {
4582
    return !representation().IsTagged();
4583
  }
4584

    
4585
  virtual HValue* EnsureAndPropagateNotMinusZero(
4586
      BitVector* visited) V8_OVERRIDE;
4587

    
4588
  virtual HValue* Canonicalize() V8_OVERRIDE;
4589

    
4590
  virtual bool TryDecompose(DecompositionResult* decomposition) V8_OVERRIDE {
4591
    if (left()->IsInteger32Constant()) {
4592
      decomposition->Apply(right(), left()->GetInteger32Constant());
4593
      return true;
4594
    } else if (right()->IsInteger32Constant()) {
4595
      decomposition->Apply(left(), right()->GetInteger32Constant());
4596
      return true;
4597
    } else {
4598
      return false;
4599
    }
4600
  }
4601

    
4602
  virtual void RepresentationChanged(Representation to) V8_OVERRIDE {
4603
    if (to.IsTagged()) {
4604
      SetGVNFlag(kChangesNewSpacePromotion);
4605
      ClearFlag(kAllowUndefinedAsNaN);
4606
    }
4607
    if (to.IsTagged() &&
4608
        (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved() ||
4609
         left()->ToStringCanBeObserved() || right()->ToStringCanBeObserved())) {
4610
      SetAllSideEffects();
4611
      ClearFlag(kUseGVN);
4612
    } else {
4613
      ClearAllSideEffects();
4614
      SetFlag(kUseGVN);
4615
    }
4616
  }
4617

    
4618
  DECLARE_CONCRETE_INSTRUCTION(Add)
4619

    
4620
 protected:
4621
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4622

    
4623
  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4624

    
4625
 private:
4626
  HAdd(HValue* context, HValue* left, HValue* right)
4627
      : HArithmeticBinaryOperation(context, left, right) {
4628
    SetFlag(kCanOverflow);
4629
  }
4630
};
4631

    
4632

    
4633
class HSub V8_FINAL : public HArithmeticBinaryOperation {
4634
 public:
4635
  static HInstruction* New(Zone* zone,
4636
                           HValue* context,
4637
                           HValue* left,
4638
                           HValue* right);
4639

    
4640
  virtual HValue* EnsureAndPropagateNotMinusZero(
4641
      BitVector* visited) V8_OVERRIDE;
4642

    
4643
  virtual HValue* Canonicalize() V8_OVERRIDE;
4644

    
4645
  virtual bool TryDecompose(DecompositionResult* decomposition) V8_OVERRIDE {
4646
    if (right()->IsInteger32Constant()) {
4647
      decomposition->Apply(left(), -right()->GetInteger32Constant());
4648
      return true;
4649
    } else {
4650
      return false;
4651
    }
4652
  }
4653

    
4654
  DECLARE_CONCRETE_INSTRUCTION(Sub)
4655

    
4656
 protected:
4657
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4658

    
4659
  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4660

    
4661
 private:
4662
  HSub(HValue* context, HValue* left, HValue* right)
4663
      : HArithmeticBinaryOperation(context, left, right) {
4664
    SetFlag(kCanOverflow);
4665
  }
4666
};
4667

    
4668

    
4669
class HMul V8_FINAL : public HArithmeticBinaryOperation {
4670
 public:
4671
  static HInstruction* New(Zone* zone,
4672
                           HValue* context,
4673
                           HValue* left,
4674
                           HValue* right);
4675

    
4676
  static HInstruction* NewImul(Zone* zone,
4677
                         HValue* context,
4678
                         HValue* left,
4679
                         HValue* right) {
4680
    HInstruction* instr = HMul::New(zone, context, left, right);
4681
    if (!instr->IsMul()) return instr;
4682
    HMul* mul = HMul::cast(instr);
4683
    // TODO(mstarzinger): Prevent bailout on minus zero for imul.
4684
    mul->AssumeRepresentation(Representation::Integer32());
4685
    mul->ClearFlag(HValue::kCanOverflow);
4686
    return mul;
4687
  }
4688

    
4689
  virtual HValue* EnsureAndPropagateNotMinusZero(
4690
      BitVector* visited) V8_OVERRIDE;
4691

    
4692
  virtual HValue* Canonicalize() V8_OVERRIDE;
4693

    
4694
  // Only commutative if it is certain that not two objects are multiplicated.
4695
  virtual bool IsCommutative() const V8_OVERRIDE {
4696
    return !representation().IsTagged();
4697
  }
4698

    
4699
  virtual void UpdateRepresentation(Representation new_rep,
4700
                                    HInferRepresentationPhase* h_infer,
4701
                                    const char* reason) V8_OVERRIDE {
4702
    HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4703
  }
4704

    
4705
  bool MulMinusOne();
4706

    
4707
  DECLARE_CONCRETE_INSTRUCTION(Mul)
4708

    
4709
 protected:
4710
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4711

    
4712
  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4713

    
4714
 private:
4715
  HMul(HValue* context, HValue* left, HValue* right)
4716
      : HArithmeticBinaryOperation(context, left, right) {
4717
    SetFlag(kCanOverflow);
4718
  }
4719
};
4720

    
4721

    
4722
class HMod V8_FINAL : public HArithmeticBinaryOperation {
4723
 public:
4724
  static HInstruction* New(Zone* zone,
4725
                           HValue* context,
4726
                           HValue* left,
4727
                           HValue* right,
4728
                           Maybe<int> fixed_right_arg);
4729

    
4730
  Maybe<int> fixed_right_arg() const { return fixed_right_arg_; }
4731

    
4732
  bool HasPowerOf2Divisor() {
4733
    if (right()->IsConstant() &&
4734
        HConstant::cast(right())->HasInteger32Value()) {
4735
      int32_t value = HConstant::cast(right())->Integer32Value();
4736
      return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value));
4737
    }
4738

    
4739
    return false;
4740
  }
4741

    
4742
  virtual HValue* EnsureAndPropagateNotMinusZero(
4743
      BitVector* visited) V8_OVERRIDE;
4744

    
4745
  virtual HValue* Canonicalize() V8_OVERRIDE;
4746

    
4747
  virtual void UpdateRepresentation(Representation new_rep,
4748
                                    HInferRepresentationPhase* h_infer,
4749
                                    const char* reason) V8_OVERRIDE {
4750
    if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4751
    HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4752
  }
4753

    
4754
  DECLARE_CONCRETE_INSTRUCTION(Mod)
4755

    
4756
 protected:
4757
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4758

    
4759
  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4760

    
4761
 private:
4762
  HMod(HValue* context,
4763
       HValue* left,
4764
       HValue* right,
4765
       Maybe<int> fixed_right_arg)
4766
      : HArithmeticBinaryOperation(context, left, right),
4767
        fixed_right_arg_(fixed_right_arg) {
4768
    SetFlag(kCanBeDivByZero);
4769
    SetFlag(kCanOverflow);
4770
  }
4771

    
4772
  const Maybe<int> fixed_right_arg_;
4773
};
4774

    
4775

    
4776
class HDiv V8_FINAL : public HArithmeticBinaryOperation {
4777
 public:
4778
  static HInstruction* New(Zone* zone,
4779
                           HValue* context,
4780
                           HValue* left,
4781
                           HValue* right);
4782

    
4783
  bool HasPowerOf2Divisor() {
4784
    if (right()->IsInteger32Constant()) {
4785
      int32_t value = right()->GetInteger32Constant();
4786
      return value != 0 && (IsPowerOf2(value) || IsPowerOf2(-value));
4787
    }
4788

    
4789
    return false;
4790
  }
4791

    
4792
  virtual HValue* EnsureAndPropagateNotMinusZero(
4793
      BitVector* visited) V8_OVERRIDE;
4794

    
4795
  virtual HValue* Canonicalize() V8_OVERRIDE;
4796

    
4797
  virtual void UpdateRepresentation(Representation new_rep,
4798
                                    HInferRepresentationPhase* h_infer,
4799
                                    const char* reason) V8_OVERRIDE {
4800
    if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4801
    HArithmeticBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4802
  }
4803

    
4804
  DECLARE_CONCRETE_INSTRUCTION(Div)
4805

    
4806
 protected:
4807
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4808

    
4809
  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4810

    
4811
 private:
4812
  HDiv(HValue* context, HValue* left, HValue* right)
4813
      : HArithmeticBinaryOperation(context, left, right) {
4814
    SetFlag(kCanBeDivByZero);
4815
    SetFlag(kCanOverflow);
4816
  }
4817
};
4818

    
4819

    
4820
class HMathMinMax V8_FINAL : public HArithmeticBinaryOperation {
4821
 public:
4822
  enum Operation { kMathMin, kMathMax };
4823

    
4824
  static HInstruction* New(Zone* zone,
4825
                           HValue* context,
4826
                           HValue* left,
4827
                           HValue* right,
4828
                           Operation op);
4829

    
4830
  virtual Representation observed_input_representation(int index) V8_OVERRIDE {
4831
    return RequiredInputRepresentation(index);
4832
  }
4833

    
4834
  virtual void InferRepresentation(
4835
      HInferRepresentationPhase* h_infer) V8_OVERRIDE;
4836

    
4837
  virtual Representation RepresentationFromInputs() V8_OVERRIDE {
4838
    Representation left_rep = left()->representation();
4839
    Representation right_rep = right()->representation();
4840
    Representation result = Representation::Smi();
4841
    result = result.generalize(left_rep);
4842
    result = result.generalize(right_rep);
4843
    if (result.IsTagged()) return Representation::Double();
4844
    return result;
4845
  }
4846

    
4847
  virtual bool IsCommutative() const V8_OVERRIDE { return true; }
4848

    
4849
  Operation operation() { return operation_; }
4850

    
4851
  DECLARE_CONCRETE_INSTRUCTION(MathMinMax)
4852

    
4853
 protected:
4854
  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
4855
    return other->IsMathMinMax() &&
4856
        HMathMinMax::cast(other)->operation_ == operation_;
4857
  }
4858

    
4859
  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4860

    
4861
 private:
4862
  HMathMinMax(HValue* context, HValue* left, HValue* right, Operation op)
4863
      : HArithmeticBinaryOperation(context, left, right),
4864
        operation_(op) { }
4865

    
4866
  Operation operation_;
4867
};
4868

    
4869

    
4870
class HBitwise V8_FINAL : public HBitwiseBinaryOperation {
4871
 public:
4872
  static HInstruction* New(Zone* zone,
4873
                           HValue* context,
4874
                           Token::Value op,
4875
                           HValue* left,
4876
                           HValue* right);
4877

    
4878
  Token::Value op() const { return op_; }
4879

    
4880
  virtual bool IsCommutative() const V8_OVERRIDE { return true; }
4881

    
4882
  virtual HValue* Canonicalize() V8_OVERRIDE;
4883

    
4884
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
4885

    
4886
  DECLARE_CONCRETE_INSTRUCTION(Bitwise)
4887

    
4888
 protected:
4889
  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
4890
    return op() == HBitwise::cast(other)->op();
4891
  }
4892

    
4893
  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4894

    
4895
 private:
4896
  HBitwise(HValue* context,
4897
           Token::Value op,
4898
           HValue* left,
4899
           HValue* right)
4900
      : HBitwiseBinaryOperation(context, left, right, HType::TaggedNumber()),
4901
        op_(op) {
4902
    ASSERT(op == Token::BIT_AND || op == Token::BIT_OR || op == Token::BIT_XOR);
4903
    // BIT_AND with a smi-range positive value will always unset the
4904
    // entire sign-extension of the smi-sign.
4905
    if (op == Token::BIT_AND &&
4906
        ((left->IsConstant() &&
4907
          left->representation().IsSmi() &&
4908
          HConstant::cast(left)->Integer32Value() >= 0) ||
4909
         (right->IsConstant() &&
4910
          right->representation().IsSmi() &&
4911
          HConstant::cast(right)->Integer32Value() >= 0))) {
4912
      SetFlag(kTruncatingToSmi);
4913
      SetFlag(kTruncatingToInt32);
4914
    // BIT_OR with a smi-range negative value will always set the entire
4915
    // sign-extension of the smi-sign.
4916
    } else if (op == Token::BIT_OR &&
4917
        ((left->IsConstant() &&
4918
          left->representation().IsSmi() &&
4919
          HConstant::cast(left)->Integer32Value() < 0) ||
4920
         (right->IsConstant() &&
4921
          right->representation().IsSmi() &&
4922
          HConstant::cast(right)->Integer32Value() < 0))) {
4923
      SetFlag(kTruncatingToSmi);
4924
      SetFlag(kTruncatingToInt32);
4925
    }
4926
  }
4927

    
4928
  Token::Value op_;
4929
};
4930

    
4931

    
4932
class HShl V8_FINAL : public HBitwiseBinaryOperation {
4933
 public:
4934
  static HInstruction* New(Zone* zone,
4935
                           HValue* context,
4936
                           HValue* left,
4937
                           HValue* right);
4938

    
4939
  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4940

    
4941
  virtual void UpdateRepresentation(Representation new_rep,
4942
                                    HInferRepresentationPhase* h_infer,
4943
                                    const char* reason) V8_OVERRIDE {
4944
    if (new_rep.IsSmi() &&
4945
        !(right()->IsInteger32Constant() &&
4946
          right()->GetInteger32Constant() >= 0)) {
4947
      new_rep = Representation::Integer32();
4948
    }
4949
    HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4950
  }
4951

    
4952
  DECLARE_CONCRETE_INSTRUCTION(Shl)
4953

    
4954
 protected:
4955
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4956

    
4957
 private:
4958
  HShl(HValue* context, HValue* left, HValue* right)
4959
      : HBitwiseBinaryOperation(context, left, right) { }
4960
};
4961

    
4962

    
4963
class HShr V8_FINAL : public HBitwiseBinaryOperation {
4964
 public:
4965
  static HInstruction* New(Zone* zone,
4966
                           HValue* context,
4967
                           HValue* left,
4968
                           HValue* right);
4969

    
4970
  virtual bool TryDecompose(DecompositionResult* decomposition) V8_OVERRIDE {
4971
    if (right()->IsInteger32Constant()) {
4972
      if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
4973
        // This is intended to look for HAdd and HSub, to handle compounds
4974
        // like ((base + offset) >> scale) with one single decomposition.
4975
        left()->TryDecompose(decomposition);
4976
        return true;
4977
      }
4978
    }
4979
    return false;
4980
  }
4981

    
4982
  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
4983

    
4984
  virtual void UpdateRepresentation(Representation new_rep,
4985
                                    HInferRepresentationPhase* h_infer,
4986
                                    const char* reason) V8_OVERRIDE {
4987
    if (new_rep.IsSmi()) new_rep = Representation::Integer32();
4988
    HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
4989
  }
4990

    
4991
  DECLARE_CONCRETE_INSTRUCTION(Shr)
4992

    
4993
 protected:
4994
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
4995

    
4996
 private:
4997
  HShr(HValue* context, HValue* left, HValue* right)
4998
      : HBitwiseBinaryOperation(context, left, right) { }
4999
};
5000

    
5001

    
5002
class HSar V8_FINAL : public HBitwiseBinaryOperation {
5003
 public:
5004
  static HInstruction* New(Zone* zone,
5005
                           HValue* context,
5006
                           HValue* left,
5007
                           HValue* right);
5008

    
5009
  virtual bool TryDecompose(DecompositionResult* decomposition) V8_OVERRIDE {
5010
    if (right()->IsInteger32Constant()) {
5011
      if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) {
5012
        // This is intended to look for HAdd and HSub, to handle compounds
5013
        // like ((base + offset) >> scale) with one single decomposition.
5014
        left()->TryDecompose(decomposition);
5015
        return true;
5016
      }
5017
    }
5018
    return false;
5019
  }
5020

    
5021
  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
5022

    
5023
  virtual void UpdateRepresentation(Representation new_rep,
5024
                                    HInferRepresentationPhase* h_infer,
5025
                                    const char* reason) V8_OVERRIDE {
5026
    if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5027
    HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5028
  }
5029

    
5030
  DECLARE_CONCRETE_INSTRUCTION(Sar)
5031

    
5032
 protected:
5033
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
5034

    
5035
 private:
5036
  HSar(HValue* context, HValue* left, HValue* right)
5037
      : HBitwiseBinaryOperation(context, left, right) { }
5038
};
5039

    
5040

    
5041
class HRor V8_FINAL : public HBitwiseBinaryOperation {
5042
 public:
5043
  static HInstruction* New(Zone* zone,
5044
                           HValue* context,
5045
                           HValue* left,
5046
                           HValue* right) {
5047
    return new(zone) HRor(context, left, right);
5048
  }
5049

    
5050
  virtual void UpdateRepresentation(Representation new_rep,
5051
                                    HInferRepresentationPhase* h_infer,
5052
                                    const char* reason) V8_OVERRIDE {
5053
    if (new_rep.IsSmi()) new_rep = Representation::Integer32();
5054
    HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason);
5055
  }
5056

    
5057
  DECLARE_CONCRETE_INSTRUCTION(Ror)
5058

    
5059
 protected:
5060
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
5061

    
5062
 private:
5063
  HRor(HValue* context, HValue* left, HValue* right)
5064
       : HBitwiseBinaryOperation(context, left, right) {
5065
    ChangeRepresentation(Representation::Integer32());
5066
  }
5067
};
5068

    
5069

    
5070
class HOsrEntry V8_FINAL : public HTemplateInstruction<0> {
5071
 public:
5072
  DECLARE_INSTRUCTION_FACTORY_P1(HOsrEntry, BailoutId);
5073

    
5074
  BailoutId ast_id() const { return ast_id_; }
5075

    
5076
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5077
    return Representation::None();
5078
  }
5079

    
5080
  DECLARE_CONCRETE_INSTRUCTION(OsrEntry)
5081

    
5082
 private:
5083
  explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
5084
    SetGVNFlag(kChangesOsrEntries);
5085
    SetGVNFlag(kChangesNewSpacePromotion);
5086
  }
5087

    
5088
  BailoutId ast_id_;
5089
};
5090

    
5091

    
5092
class HParameter V8_FINAL : public HTemplateInstruction<0> {
5093
 public:
5094
  enum ParameterKind {
5095
    STACK_PARAMETER,
5096
    REGISTER_PARAMETER
5097
  };
5098

    
5099
  DECLARE_INSTRUCTION_FACTORY_P1(HParameter, unsigned);
5100
  DECLARE_INSTRUCTION_FACTORY_P2(HParameter, unsigned, ParameterKind);
5101
  DECLARE_INSTRUCTION_FACTORY_P3(HParameter, unsigned, ParameterKind,
5102
                                 Representation);
5103

    
5104
  unsigned index() const { return index_; }
5105
  ParameterKind kind() const { return kind_; }
5106

    
5107
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5108

    
5109
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5110
    return Representation::None();
5111
  }
5112

    
5113
  DECLARE_CONCRETE_INSTRUCTION(Parameter)
5114

    
5115
 private:
5116
  explicit HParameter(unsigned index,
5117
                      ParameterKind kind = STACK_PARAMETER)
5118
      : index_(index),
5119
        kind_(kind) {
5120
    set_representation(Representation::Tagged());
5121
  }
5122

    
5123
  explicit HParameter(unsigned index,
5124
                      ParameterKind kind,
5125
                      Representation r)
5126
      : index_(index),
5127
        kind_(kind) {
5128
    set_representation(r);
5129
  }
5130

    
5131
  unsigned index_;
5132
  ParameterKind kind_;
5133
};
5134

    
5135

    
5136
class HCallStub V8_FINAL : public HUnaryCall {
5137
 public:
5138
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HCallStub, CodeStub::Major, int);
5139
  CodeStub::Major major_key() { return major_key_; }
5140

    
5141
  HValue* context() { return value(); }
5142

    
5143
  void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
5144
    transcendental_type_ = transcendental_type;
5145
  }
5146
  TranscendentalCache::Type transcendental_type() {
5147
    return transcendental_type_;
5148
  }
5149

    
5150
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5151

    
5152
  DECLARE_CONCRETE_INSTRUCTION(CallStub)
5153

    
5154
 private:
5155
  HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
5156
      : HUnaryCall(context, argument_count),
5157
        major_key_(major_key),
5158
        transcendental_type_(TranscendentalCache::kNumberOfCaches) {
5159
  }
5160

    
5161
  CodeStub::Major major_key_;
5162
  TranscendentalCache::Type transcendental_type_;
5163
};
5164

    
5165

    
5166
class HUnknownOSRValue V8_FINAL : public HTemplateInstruction<0> {
5167
 public:
5168
  DECLARE_INSTRUCTION_FACTORY_P2(HUnknownOSRValue, HEnvironment*, int);
5169

    
5170
  virtual void PrintDataTo(StringStream* stream);
5171

    
5172
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5173
    return Representation::None();
5174
  }
5175

    
5176
  void set_incoming_value(HPhi* value) { incoming_value_ = value; }
5177
  HPhi* incoming_value() { return incoming_value_; }
5178
  HEnvironment *environment() { return environment_; }
5179
  int index() { return index_; }
5180

    
5181
  virtual Representation KnownOptimalRepresentation() V8_OVERRIDE {
5182
    if (incoming_value_ == NULL) return Representation::None();
5183
    return incoming_value_->KnownOptimalRepresentation();
5184
  }
5185

    
5186
  DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue)
5187

    
5188
 private:
5189
  HUnknownOSRValue(HEnvironment* environment, int index)
5190
      : environment_(environment),
5191
        index_(index),
5192
        incoming_value_(NULL) {
5193
    set_representation(Representation::Tagged());
5194
  }
5195

    
5196
  HEnvironment* environment_;
5197
  int index_;
5198
  HPhi* incoming_value_;
5199
};
5200

    
5201

    
5202
class HLoadGlobalCell V8_FINAL : public HTemplateInstruction<0> {
5203
 public:
5204
  DECLARE_INSTRUCTION_FACTORY_P2(HLoadGlobalCell, Handle<Cell>,
5205
                                 PropertyDetails);
5206

    
5207
  Unique<Cell> cell() const { return cell_; }
5208
  bool RequiresHoleCheck() const;
5209

    
5210
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5211

    
5212
  virtual intptr_t Hashcode() V8_OVERRIDE {
5213
    return cell_.Hashcode();
5214
  }
5215

    
5216
  virtual void FinalizeUniqueness() V8_OVERRIDE {
5217
    cell_ = Unique<Cell>(cell_.handle());
5218
  }
5219

    
5220
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5221
    return Representation::None();
5222
  }
5223

    
5224
  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell)
5225

    
5226
 protected:
5227
  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
5228
    return cell_ == HLoadGlobalCell::cast(other)->cell_;
5229
  }
5230

    
5231
 private:
5232
  HLoadGlobalCell(Handle<Cell> cell, PropertyDetails details)
5233
    : cell_(Unique<Cell>::CreateUninitialized(cell)), details_(details) {
5234
    set_representation(Representation::Tagged());
5235
    SetFlag(kUseGVN);
5236
    SetGVNFlag(kDependsOnGlobalVars);
5237
  }
5238

    
5239
  virtual bool IsDeletable() const V8_OVERRIDE { return !RequiresHoleCheck(); }
5240

    
5241
  Unique<Cell> cell_;
5242
  PropertyDetails details_;
5243
};
5244

    
5245

    
5246
class HLoadGlobalGeneric V8_FINAL : public HTemplateInstruction<2> {
5247
 public:
5248
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HLoadGlobalGeneric, HValue*,
5249
                                              Handle<Object>, bool);
5250

    
5251
  HValue* context() { return OperandAt(0); }
5252
  HValue* global_object() { return OperandAt(1); }
5253
  Handle<Object> name() const { return name_; }
5254
  bool for_typeof() const { return for_typeof_; }
5255

    
5256
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5257

    
5258
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5259
    return Representation::Tagged();
5260
  }
5261

    
5262
  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric)
5263

    
5264
 private:
5265
  HLoadGlobalGeneric(HValue* context,
5266
                     HValue* global_object,
5267
                     Handle<Object> name,
5268
                     bool for_typeof)
5269
      : name_(name),
5270
        for_typeof_(for_typeof) {
5271
    SetOperandAt(0, context);
5272
    SetOperandAt(1, global_object);
5273
    set_representation(Representation::Tagged());
5274
    SetAllSideEffects();
5275
  }
5276

    
5277
  Handle<Object> name_;
5278
  bool for_typeof_;
5279
};
5280

    
5281

    
5282
class HAllocate V8_FINAL : public HTemplateInstruction<2> {
5283
 public:
5284
  static HAllocate* New(Zone* zone,
5285
                        HValue* context,
5286
                        HValue* size,
5287
                        HType type,
5288
                        PretenureFlag pretenure_flag,
5289
                        InstanceType instance_type) {
5290
    return new(zone) HAllocate(context, size, type, pretenure_flag,
5291
        instance_type);
5292
  }
5293

    
5294
  // Maximum instance size for which allocations will be inlined.
5295
  static const int kMaxInlineSize = 64 * kPointerSize;
5296

    
5297
  HValue* context() { return OperandAt(0); }
5298
  HValue* size() { return OperandAt(1); }
5299

    
5300
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5301
    if (index == 0) {
5302
      return Representation::Tagged();
5303
    } else {
5304
      return Representation::Integer32();
5305
    }
5306
  }
5307

    
5308
  virtual Handle<Map> GetMonomorphicJSObjectMap() {
5309
    return known_initial_map_;
5310
  }
5311

    
5312
  void set_known_initial_map(Handle<Map> known_initial_map) {
5313
    known_initial_map_ = known_initial_map;
5314
  }
5315

    
5316
  bool IsNewSpaceAllocation() const {
5317
    return (flags_ & ALLOCATE_IN_NEW_SPACE) != 0;
5318
  }
5319

    
5320
  bool IsOldDataSpaceAllocation() const {
5321
    return (flags_ & ALLOCATE_IN_OLD_DATA_SPACE) != 0;
5322
  }
5323

    
5324
  bool IsOldPointerSpaceAllocation() const {
5325
    return (flags_ & ALLOCATE_IN_OLD_POINTER_SPACE) != 0;
5326
  }
5327

    
5328
  bool MustAllocateDoubleAligned() const {
5329
    return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0;
5330
  }
5331

    
5332
  bool MustPrefillWithFiller() const {
5333
    return (flags_ & PREFILL_WITH_FILLER) != 0;
5334
  }
5335

    
5336
  void MakePrefillWithFiller() {
5337
    flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER);
5338
  }
5339

    
5340
  void MakeDoubleAligned() {
5341
    flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED);
5342
  }
5343

    
5344
  virtual void HandleSideEffectDominator(GVNFlag side_effect,
5345
                                         HValue* dominator) V8_OVERRIDE;
5346

    
5347
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5348

    
5349
  DECLARE_CONCRETE_INSTRUCTION(Allocate)
5350

    
5351
 private:
5352
  enum Flags {
5353
    ALLOCATE_IN_NEW_SPACE = 1 << 0,
5354
    ALLOCATE_IN_OLD_DATA_SPACE = 1 << 1,
5355
    ALLOCATE_IN_OLD_POINTER_SPACE = 1 << 2,
5356
    ALLOCATE_DOUBLE_ALIGNED = 1 << 3,
5357
    PREFILL_WITH_FILLER = 1 << 4
5358
  };
5359

    
5360
  HAllocate(HValue* context,
5361
            HValue* size,
5362
            HType type,
5363
            PretenureFlag pretenure_flag,
5364
            InstanceType instance_type)
5365
      : HTemplateInstruction<2>(type),
5366
        dominating_allocate_(NULL),
5367
        filler_free_space_size_(NULL),
5368
        clear_next_map_word_(false) {
5369
    SetOperandAt(0, context);
5370
    SetOperandAt(1, size);
5371
    set_representation(Representation::Tagged());
5372
    SetFlag(kTrackSideEffectDominators);
5373
    SetGVNFlag(kChangesNewSpacePromotion);
5374
    SetGVNFlag(kDependsOnNewSpacePromotion);
5375
    flags_ = pretenure_flag == TENURED
5376
        ? (Heap::TargetSpaceId(instance_type) == OLD_POINTER_SPACE
5377
            ? ALLOCATE_IN_OLD_POINTER_SPACE : ALLOCATE_IN_OLD_DATA_SPACE)
5378
        : ALLOCATE_IN_NEW_SPACE;
5379
    if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
5380
      flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED);
5381
    }
5382
    // We have to fill the allocated object with one word fillers if we do
5383
    // not use allocation folding since some allocations may depend on each
5384
    // other, i.e., have a pointer to each other. A GC in between these
5385
    // allocations may leave such objects behind in a not completely initialized
5386
    // state.
5387
    if (!FLAG_use_gvn || !FLAG_use_allocation_folding) {
5388
      flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER);
5389
    }
5390
    clear_next_map_word_ = pretenure_flag == NOT_TENURED &&
5391
        AllocationSite::CanTrack(instance_type);
5392
  }
5393

    
5394
  void UpdateSize(HValue* size) {
5395
    SetOperandAt(1, size);
5396
  }
5397

    
5398
  HAllocate* GetFoldableDominator(HAllocate* dominator);
5399

    
5400
  void UpdateFreeSpaceFiller(int32_t filler_size);
5401

    
5402
  void CreateFreeSpaceFiller(int32_t filler_size);
5403

    
5404
  bool IsFoldable(HAllocate* allocate) {
5405
    return (IsNewSpaceAllocation() && allocate->IsNewSpaceAllocation()) ||
5406
        (IsOldDataSpaceAllocation() && allocate->IsOldDataSpaceAllocation()) ||
5407
        (IsOldPointerSpaceAllocation() &&
5408
            allocate->IsOldPointerSpaceAllocation());
5409
  }
5410

    
5411
  void ClearNextMapWord(int offset);
5412

    
5413
  Flags flags_;
5414
  Handle<Map> known_initial_map_;
5415
  HAllocate* dominating_allocate_;
5416
  HStoreNamedField* filler_free_space_size_;
5417
  bool clear_next_map_word_;
5418
};
5419

    
5420

    
5421
class HStoreCodeEntry V8_FINAL: public HTemplateInstruction<2> {
5422
 public:
5423
  static HStoreCodeEntry* New(Zone* zone,
5424
                              HValue* context,
5425
                              HValue* function,
5426
                              HValue* code) {
5427
    return new(zone) HStoreCodeEntry(function, code);
5428
  }
5429

    
5430
  virtual Representation RequiredInputRepresentation(int index) {
5431
    return Representation::Tagged();
5432
  }
5433

    
5434
  HValue* function() { return OperandAt(0); }
5435
  HValue* code_object() { return OperandAt(1); }
5436

    
5437
  DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry)
5438

    
5439
 private:
5440
  HStoreCodeEntry(HValue* function, HValue* code) {
5441
    SetOperandAt(0, function);
5442
    SetOperandAt(1, code);
5443
  }
5444
};
5445

    
5446

    
5447
class HInnerAllocatedObject V8_FINAL: public HTemplateInstruction<1> {
5448
 public:
5449
  static HInnerAllocatedObject* New(Zone* zone,
5450
                                    HValue* context,
5451
                                    HValue* value,
5452
                                    int offset,
5453
                                    HType type = HType::Tagged()) {
5454
    return new(zone) HInnerAllocatedObject(value, offset, type);
5455
  }
5456

    
5457
  HValue* base_object() { return OperandAt(0); }
5458
  int offset() { return offset_; }
5459

    
5460
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5461
    return Representation::Tagged();
5462
  }
5463

    
5464
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5465

    
5466
  DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject)
5467

    
5468
 private:
5469
  HInnerAllocatedObject(HValue* value, int offset, HType type = HType::Tagged())
5470
      : HTemplateInstruction<1>(type), offset_(offset) {
5471
    ASSERT(value->IsAllocate());
5472
    SetOperandAt(0, value);
5473
    set_type(type);
5474
    set_representation(Representation::Tagged());
5475
  }
5476

    
5477
  int offset_;
5478
};
5479

    
5480

    
5481
inline bool StoringValueNeedsWriteBarrier(HValue* value) {
5482
  return !value->type().IsBoolean()
5483
      && !value->type().IsSmi()
5484
      && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable());
5485
}
5486

    
5487

    
5488
inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
5489
                                            HValue* new_space_dominator) {
5490
  if (object->IsInnerAllocatedObject()) {
5491
    return ReceiverObjectNeedsWriteBarrier(
5492
        HInnerAllocatedObject::cast(object)->base_object(),
5493
        new_space_dominator);
5494
  }
5495
  if (object->IsConstant() && HConstant::cast(object)->IsCell()) {
5496
    return false;
5497
  }
5498
  if (object->IsConstant() &&
5499
      HConstant::cast(object)->HasExternalReferenceValue()) {
5500
    // Stores to external references require no write barriers
5501
    return false;
5502
  }
5503
  if (object != new_space_dominator) return true;
5504
  if (object->IsAllocate()) {
5505
    return !HAllocate::cast(object)->IsNewSpaceAllocation();
5506
  }
5507
  return true;
5508
}
5509

    
5510

    
5511
class HStoreGlobalCell V8_FINAL : public HUnaryOperation {
5512
 public:
5513
  DECLARE_INSTRUCTION_FACTORY_P3(HStoreGlobalCell, HValue*,
5514
                                 Handle<PropertyCell>, PropertyDetails);
5515

    
5516
  Unique<PropertyCell> cell() const { return cell_; }
5517
  bool RequiresHoleCheck() {
5518
    return !details_.IsDontDelete() || details_.IsReadOnly();
5519
  }
5520
  bool NeedsWriteBarrier() {
5521
    return StoringValueNeedsWriteBarrier(value());
5522
  }
5523

    
5524
  virtual void FinalizeUniqueness() V8_OVERRIDE {
5525
    cell_ = Unique<PropertyCell>(cell_.handle());
5526
  }
5527

    
5528
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5529
    return Representation::Tagged();
5530
  }
5531
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5532

    
5533
  DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell)
5534

    
5535
 private:
5536
  HStoreGlobalCell(HValue* value,
5537
                   Handle<PropertyCell> cell,
5538
                   PropertyDetails details)
5539
      : HUnaryOperation(value),
5540
        cell_(Unique<PropertyCell>::CreateUninitialized(cell)),
5541
        details_(details) {
5542
    SetGVNFlag(kChangesGlobalVars);
5543
  }
5544

    
5545
  Unique<PropertyCell> cell_;
5546
  PropertyDetails details_;
5547
};
5548

    
5549

    
5550
class HStoreGlobalGeneric : public HTemplateInstruction<3> {
5551
 public:
5552
  inline static HStoreGlobalGeneric* New(Zone* zone,
5553
                                         HValue* context,
5554
                                         HValue* global_object,
5555
                                         Handle<Object> name,
5556
                                         HValue* value,
5557
                                         StrictModeFlag strict_mode_flag) {
5558
    return new(zone) HStoreGlobalGeneric(context, global_object,
5559
                                         name, value, strict_mode_flag);
5560
  }
5561

    
5562
  HValue* context() { return OperandAt(0); }
5563
  HValue* global_object() { return OperandAt(1); }
5564
  Handle<Object> name() const { return name_; }
5565
  HValue* value() { return OperandAt(2); }
5566
  StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
5567

    
5568
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5569

    
5570
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5571
    return Representation::Tagged();
5572
  }
5573

    
5574
  DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric)
5575

    
5576
 private:
5577
  HStoreGlobalGeneric(HValue* context,
5578
                      HValue* global_object,
5579
                      Handle<Object> name,
5580
                      HValue* value,
5581
                      StrictModeFlag strict_mode_flag)
5582
      : name_(name),
5583
        strict_mode_flag_(strict_mode_flag) {
5584
    SetOperandAt(0, context);
5585
    SetOperandAt(1, global_object);
5586
    SetOperandAt(2, value);
5587
    set_representation(Representation::Tagged());
5588
    SetAllSideEffects();
5589
  }
5590

    
5591
  Handle<Object> name_;
5592
  StrictModeFlag strict_mode_flag_;
5593
};
5594

    
5595

    
5596
class HLoadContextSlot V8_FINAL : public HUnaryOperation {
5597
 public:
5598
  enum Mode {
5599
    // Perform a normal load of the context slot without checking its value.
5600
    kNoCheck,
5601
    // Load and check the value of the context slot. Deoptimize if it's the
5602
    // hole value. This is used for checking for loading of uninitialized
5603
    // harmony bindings where we deoptimize into full-codegen generated code
5604
    // which will subsequently throw a reference error.
5605
    kCheckDeoptimize,
5606
    // Load and check the value of the context slot. Return undefined if it's
5607
    // the hole value. This is used for non-harmony const assignments
5608
    kCheckReturnUndefined
5609
  };
5610

    
5611
  HLoadContextSlot(HValue* context, Variable* var)
5612
      : HUnaryOperation(context), slot_index_(var->index()) {
5613
    ASSERT(var->IsContextSlot());
5614
    switch (var->mode()) {
5615
      case LET:
5616
      case CONST_HARMONY:
5617
        mode_ = kCheckDeoptimize;
5618
        break;
5619
      case CONST:
5620
        mode_ = kCheckReturnUndefined;
5621
        break;
5622
      default:
5623
        mode_ = kNoCheck;
5624
    }
5625
    set_representation(Representation::Tagged());
5626
    SetFlag(kUseGVN);
5627
    SetGVNFlag(kDependsOnContextSlots);
5628
  }
5629

    
5630
  int slot_index() const { return slot_index_; }
5631
  Mode mode() const { return mode_; }
5632

    
5633
  bool DeoptimizesOnHole() {
5634
    return mode_ == kCheckDeoptimize;
5635
  }
5636

    
5637
  bool RequiresHoleCheck() const {
5638
    return mode_ != kNoCheck;
5639
  }
5640

    
5641
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5642
    return Representation::Tagged();
5643
  }
5644

    
5645
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5646

    
5647
  DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot)
5648

    
5649
 protected:
5650
  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
5651
    HLoadContextSlot* b = HLoadContextSlot::cast(other);
5652
    return (slot_index() == b->slot_index());
5653
  }
5654

    
5655
 private:
5656
  virtual bool IsDeletable() const V8_OVERRIDE { return !RequiresHoleCheck(); }
5657

    
5658
  int slot_index_;
5659
  Mode mode_;
5660
};
5661

    
5662

    
5663
class HStoreContextSlot V8_FINAL : public HTemplateInstruction<2> {
5664
 public:
5665
  enum Mode {
5666
    // Perform a normal store to the context slot without checking its previous
5667
    // value.
5668
    kNoCheck,
5669
    // Check the previous value of the context slot and deoptimize if it's the
5670
    // hole value. This is used for checking for assignments to uninitialized
5671
    // harmony bindings where we deoptimize into full-codegen generated code
5672
    // which will subsequently throw a reference error.
5673
    kCheckDeoptimize,
5674
    // Check the previous value and ignore assignment if it isn't a hole value
5675
    kCheckIgnoreAssignment
5676
  };
5677

    
5678
  DECLARE_INSTRUCTION_FACTORY_P4(HStoreContextSlot, HValue*, int,
5679
                                 Mode, HValue*);
5680

    
5681
  HValue* context() { return OperandAt(0); }
5682
  HValue* value() { return OperandAt(1); }
5683
  int slot_index() const { return slot_index_; }
5684
  Mode mode() const { return mode_; }
5685

    
5686
  bool NeedsWriteBarrier() {
5687
    return StoringValueNeedsWriteBarrier(value());
5688
  }
5689

    
5690
  bool DeoptimizesOnHole() {
5691
    return mode_ == kCheckDeoptimize;
5692
  }
5693

    
5694
  bool RequiresHoleCheck() {
5695
    return mode_ != kNoCheck;
5696
  }
5697

    
5698
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5699
    return Representation::Tagged();
5700
  }
5701

    
5702
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5703

    
5704
  DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot)
5705

    
5706
 private:
5707
  HStoreContextSlot(HValue* context, int slot_index, Mode mode, HValue* value)
5708
      : slot_index_(slot_index), mode_(mode) {
5709
    SetOperandAt(0, context);
5710
    SetOperandAt(1, value);
5711
    SetGVNFlag(kChangesContextSlots);
5712
  }
5713

    
5714
  int slot_index_;
5715
  Mode mode_;
5716
};
5717

    
5718

    
5719
// Represents an access to a portion of an object, such as the map pointer,
5720
// array elements pointer, etc, but not accesses to array elements themselves.
5721
class HObjectAccess V8_FINAL {
5722
 public:
5723
  inline bool IsInobject() const {
5724
    return portion() != kBackingStore && portion() != kExternalMemory;
5725
  }
5726

    
5727
  inline bool IsExternalMemory() const {
5728
    return portion() == kExternalMemory;
5729
  }
5730

    
5731
  inline bool IsStringLength() const {
5732
    return portion() == kStringLengths;
5733
  }
5734

    
5735
  inline int offset() const {
5736
    return OffsetField::decode(value_);
5737
  }
5738

    
5739
  inline Representation representation() const {
5740
    return Representation::FromKind(RepresentationField::decode(value_));
5741
  }
5742

    
5743
  inline Handle<String> name() const {
5744
    return name_;
5745
  }
5746

    
5747
  inline HObjectAccess WithRepresentation(Representation representation) {
5748
    return HObjectAccess(portion(), offset(), representation, name());
5749
  }
5750

    
5751
  static HObjectAccess ForHeapNumberValue() {
5752
    return HObjectAccess(
5753
        kDouble, HeapNumber::kValueOffset, Representation::Double());
5754
  }
5755

    
5756
  static HObjectAccess ForHeapNumberValueLowestBits() {
5757
    return HObjectAccess(kDouble,
5758
                         HeapNumber::kValueOffset,
5759
                         Representation::Integer32());
5760
  }
5761

    
5762
  static HObjectAccess ForHeapNumberValueHighestBits() {
5763
    return HObjectAccess(kDouble,
5764
                         HeapNumber::kValueOffset + kIntSize,
5765
                         Representation::Integer32());
5766
  }
5767

    
5768
  static HObjectAccess ForElementsPointer() {
5769
    return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
5770
  }
5771

    
5772
  static HObjectAccess ForLiteralsPointer() {
5773
    return HObjectAccess(kInobject, JSFunction::kLiteralsOffset);
5774
  }
5775

    
5776
  static HObjectAccess ForNextFunctionLinkPointer() {
5777
    return HObjectAccess(kInobject, JSFunction::kNextFunctionLinkOffset);
5778
  }
5779

    
5780
  static HObjectAccess ForArrayLength(ElementsKind elements_kind) {
5781
    return HObjectAccess(
5782
        kArrayLengths,
5783
        JSArray::kLengthOffset,
5784
        IsFastElementsKind(elements_kind) &&
5785
            FLAG_track_fields
5786
                ? Representation::Smi() : Representation::Tagged());
5787
  }
5788

    
5789
  static HObjectAccess ForAllocationSiteOffset(int offset) {
5790
    ASSERT(offset >= HeapObject::kHeaderSize && offset < AllocationSite::kSize);
5791
    return HObjectAccess(kInobject, offset);
5792
  }
5793

    
5794
  static HObjectAccess ForAllocationSiteList() {
5795
    return HObjectAccess(kExternalMemory, 0, Representation::Tagged());
5796
  }
5797

    
5798
  static HObjectAccess ForFixedArrayLength() {
5799
    return HObjectAccess(
5800
        kArrayLengths,
5801
        FixedArray::kLengthOffset,
5802
        FLAG_track_fields ? Representation::Smi() : Representation::Tagged());
5803
  }
5804

    
5805
  static HObjectAccess ForStringLength() {
5806
    STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
5807
    return HObjectAccess(
5808
        kStringLengths,
5809
        String::kLengthOffset,
5810
        FLAG_track_fields ? Representation::Smi() : Representation::Tagged());
5811
  }
5812

    
5813
  static HObjectAccess ForPropertiesPointer() {
5814
    return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
5815
  }
5816

    
5817
  static HObjectAccess ForPrototypeOrInitialMap() {
5818
    return HObjectAccess(kInobject, JSFunction::kPrototypeOrInitialMapOffset);
5819
  }
5820

    
5821
  static HObjectAccess ForSharedFunctionInfoPointer() {
5822
    return HObjectAccess(kInobject, JSFunction::kSharedFunctionInfoOffset);
5823
  }
5824

    
5825
  static HObjectAccess ForCodeEntryPointer() {
5826
    return HObjectAccess(kInobject, JSFunction::kCodeEntryOffset);
5827
  }
5828

    
5829
  static HObjectAccess ForCodeOffset() {
5830
    return HObjectAccess(kInobject, SharedFunctionInfo::kCodeOffset);
5831
  }
5832

    
5833
  static HObjectAccess ForFirstCodeSlot() {
5834
    return HObjectAccess(kInobject, SharedFunctionInfo::kFirstCodeSlot);
5835
  }
5836

    
5837
  static HObjectAccess ForFirstContextSlot() {
5838
    return HObjectAccess(kInobject, SharedFunctionInfo::kFirstContextSlot);
5839
  }
5840

    
5841
  static HObjectAccess ForOptimizedCodeMap() {
5842
    return HObjectAccess(kInobject,
5843
                         SharedFunctionInfo::kOptimizedCodeMapOffset);
5844
  }
5845

    
5846
  static HObjectAccess ForFunctionContextPointer() {
5847
    return HObjectAccess(kInobject, JSFunction::kContextOffset);
5848
  }
5849

    
5850
  static HObjectAccess ForMap() {
5851
    return HObjectAccess(kMaps, JSObject::kMapOffset);
5852
  }
5853

    
5854
  static HObjectAccess ForMapInstanceSize() {
5855
    return HObjectAccess(kInobject,
5856
                         Map::kInstanceSizeOffset,
5857
                         Representation::Byte());
5858
  }
5859

    
5860
  static HObjectAccess ForPropertyCellValue() {
5861
    return HObjectAccess(kInobject, PropertyCell::kValueOffset);
5862
  }
5863

    
5864
  static HObjectAccess ForCellValue() {
5865
    return HObjectAccess(kInobject, Cell::kValueOffset);
5866
  }
5867

    
5868
  static HObjectAccess ForAllocationMementoSite() {
5869
    return HObjectAccess(kInobject, AllocationMemento::kAllocationSiteOffset);
5870
  }
5871

    
5872
  static HObjectAccess ForCounter() {
5873
    return HObjectAccess(kExternalMemory, 0, Representation::Integer32());
5874
  }
5875

    
5876
  // Create an access to an offset in a fixed array header.
5877
  static HObjectAccess ForFixedArrayHeader(int offset);
5878

    
5879
  // Create an access to an in-object property in a JSObject.
5880
  static HObjectAccess ForJSObjectOffset(int offset,
5881
      Representation representation = Representation::Tagged());
5882

    
5883
  // Create an access to an in-object property in a JSArray.
5884
  static HObjectAccess ForJSArrayOffset(int offset);
5885

    
5886
  static HObjectAccess ForContextSlot(int index);
5887

    
5888
  // Create an access to the backing store of an object.
5889
  static HObjectAccess ForBackingStoreOffset(int offset,
5890
      Representation representation = Representation::Tagged());
5891

    
5892
  // Create an access to a resolved field (in-object or backing store).
5893
  static HObjectAccess ForField(Handle<Map> map,
5894
      LookupResult *lookup, Handle<String> name = Handle<String>::null());
5895

    
5896
  // Create an access for the payload of a Cell or JSGlobalPropertyCell.
5897
  static HObjectAccess ForCellPayload(Isolate* isolate);
5898

    
5899
  void PrintTo(StringStream* stream);
5900

    
5901
  inline bool Equals(HObjectAccess that) const {
5902
    return value_ == that.value_;  // portion and offset must match
5903
  }
5904

    
5905
 protected:
5906
  void SetGVNFlags(HValue *instr, bool is_store);
5907

    
5908
 private:
5909
  // internal use only; different parts of an object or array
5910
  enum Portion {
5911
    kMaps,             // map of an object
5912
    kArrayLengths,     // the length of an array
5913
    kStringLengths,    // the length of a string
5914
    kElementsPointer,  // elements pointer
5915
    kBackingStore,     // some field in the backing store
5916
    kDouble,           // some double field
5917
    kInobject,         // some other in-object field
5918
    kExternalMemory    // some field in external memory
5919
  };
5920

    
5921
  HObjectAccess(Portion portion, int offset,
5922
                Representation representation = Representation::Tagged(),
5923
                Handle<String> name = Handle<String>::null())
5924
    : value_(PortionField::encode(portion) |
5925
             RepresentationField::encode(representation.kind()) |
5926
             OffsetField::encode(offset)),
5927
      name_(name) {
5928
    // assert that the fields decode correctly
5929
    ASSERT(this->offset() == offset);
5930
    ASSERT(this->portion() == portion);
5931
    ASSERT(RepresentationField::decode(value_) == representation.kind());
5932
  }
5933

    
5934
  class PortionField : public BitField<Portion, 0, 3> {};
5935
  class RepresentationField : public BitField<Representation::Kind, 3, 3> {};
5936
  class OffsetField : public BitField<int, 6, 26> {};
5937

    
5938
  uint32_t value_;  // encodes portion, representation, and offset
5939
  Handle<String> name_;
5940

    
5941
  friend class HLoadNamedField;
5942
  friend class HStoreNamedField;
5943

    
5944
  inline Portion portion() const {
5945
    return PortionField::decode(value_);
5946
  }
5947
};
5948

    
5949

    
5950
class HLoadNamedField V8_FINAL : public HTemplateInstruction<1> {
5951
 public:
5952
  DECLARE_INSTRUCTION_FACTORY_P2(HLoadNamedField, HValue*, HObjectAccess);
5953

    
5954
  HValue* object() { return OperandAt(0); }
5955
  bool HasTypeCheck() { return object()->IsCheckMaps(); }
5956
  HObjectAccess access() const { return access_; }
5957
  Representation field_representation() const {
5958
      return access_.representation();
5959
  }
5960

    
5961
  virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; }
5962
  virtual bool HasOutOfBoundsAccess(int size) V8_OVERRIDE {
5963
    return !access().IsInobject() || access().offset() >= size;
5964
  }
5965
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
5966
    if (index == 0 && access().IsExternalMemory()) {
5967
      // object must be external in case of external memory access
5968
      return Representation::External();
5969
    }
5970
    return Representation::Tagged();
5971
  }
5972
  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
5973
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
5974

    
5975
  DECLARE_CONCRETE_INSTRUCTION(LoadNamedField)
5976

    
5977
 protected:
5978
  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
5979
    HLoadNamedField* b = HLoadNamedField::cast(other);
5980
    return access_.Equals(b->access_);
5981
  }
5982

    
5983
 private:
5984
  HLoadNamedField(HValue* object, HObjectAccess access) : access_(access) {
5985
    ASSERT(object != NULL);
5986
    SetOperandAt(0, object);
5987

    
5988
    Representation representation = access.representation();
5989
    if (representation.IsByte()) {
5990
      set_representation(Representation::Integer32());
5991
    } else if (representation.IsSmi()) {
5992
      set_type(HType::Smi());
5993
      set_representation(representation);
5994
    } else if (representation.IsDouble() ||
5995
               representation.IsExternal() ||
5996
               representation.IsInteger32()) {
5997
      set_representation(representation);
5998
    } else if (FLAG_track_heap_object_fields &&
5999
               representation.IsHeapObject()) {
6000
      set_type(HType::NonPrimitive());
6001
      set_representation(Representation::Tagged());
6002
    } else {
6003
      set_representation(Representation::Tagged());
6004
    }
6005
    access.SetGVNFlags(this, false);
6006
  }
6007

    
6008
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
6009

    
6010
  HObjectAccess access_;
6011
};
6012

    
6013

    
6014
class HLoadNamedGeneric V8_FINAL : public HTemplateInstruction<2> {
6015
 public:
6016
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HLoadNamedGeneric, HValue*,
6017
                                              Handle<Object>);
6018

    
6019
  HValue* context() { return OperandAt(0); }
6020
  HValue* object() { return OperandAt(1); }
6021
  Handle<Object> name() const { return name_; }
6022

    
6023
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6024
    return Representation::Tagged();
6025
  }
6026

    
6027
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6028

    
6029
  DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
6030

    
6031
 private:
6032
  HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name)
6033
      : name_(name) {
6034
    SetOperandAt(0, context);
6035
    SetOperandAt(1, object);
6036
    set_representation(Representation::Tagged());
6037
    SetAllSideEffects();
6038
  }
6039

    
6040
  Handle<Object> name_;
6041
};
6042

    
6043

    
6044
class HLoadFunctionPrototype V8_FINAL : public HUnaryOperation {
6045
 public:
6046
  DECLARE_INSTRUCTION_FACTORY_P1(HLoadFunctionPrototype, HValue*);
6047

    
6048
  HValue* function() { return OperandAt(0); }
6049

    
6050
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6051
    return Representation::Tagged();
6052
  }
6053

    
6054
  DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype)
6055

    
6056
 protected:
6057
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
6058

    
6059
 private:
6060
  explicit HLoadFunctionPrototype(HValue* function)
6061
      : HUnaryOperation(function) {
6062
    set_representation(Representation::Tagged());
6063
    SetFlag(kUseGVN);
6064
    SetGVNFlag(kDependsOnCalls);
6065
  }
6066
};
6067

    
6068
class ArrayInstructionInterface {
6069
 public:
6070
  virtual HValue* GetKey() = 0;
6071
  virtual void SetKey(HValue* key) = 0;
6072
  virtual void SetIndexOffset(uint32_t index_offset) = 0;
6073
  virtual bool IsDehoisted() = 0;
6074
  virtual void SetDehoisted(bool is_dehoisted) = 0;
6075
  virtual ~ArrayInstructionInterface() { };
6076

    
6077
  static Representation KeyedAccessIndexRequirement(Representation r) {
6078
    return r.IsInteger32() || SmiValuesAre32Bits()
6079
        ? Representation::Integer32() : Representation::Smi();
6080
  }
6081
};
6082

    
6083

    
6084
enum LoadKeyedHoleMode {
6085
  NEVER_RETURN_HOLE,
6086
  ALLOW_RETURN_HOLE
6087
};
6088

    
6089

    
6090
class HLoadKeyed V8_FINAL
6091
    : public HTemplateInstruction<3>, public ArrayInstructionInterface {
6092
 public:
6093
  DECLARE_INSTRUCTION_FACTORY_P4(HLoadKeyed, HValue*, HValue*, HValue*,
6094
                                 ElementsKind);
6095
  DECLARE_INSTRUCTION_FACTORY_P5(HLoadKeyed, HValue*, HValue*, HValue*,
6096
                                 ElementsKind, LoadKeyedHoleMode);
6097

    
6098
  bool is_external() const {
6099
    return IsExternalArrayElementsKind(elements_kind());
6100
  }
6101
  HValue* elements() { return OperandAt(0); }
6102
  HValue* key() { return OperandAt(1); }
6103
  HValue* dependency() {
6104
    ASSERT(HasDependency());
6105
    return OperandAt(2);
6106
  }
6107
  bool HasDependency() const { return OperandAt(0) != OperandAt(2); }
6108
  uint32_t index_offset() { return IndexOffsetField::decode(bit_field_); }
6109
  void SetIndexOffset(uint32_t index_offset) {
6110
    bit_field_ = IndexOffsetField::update(bit_field_, index_offset);
6111
  }
6112
  HValue* GetKey() { return key(); }
6113
  void SetKey(HValue* key) { SetOperandAt(1, key); }
6114
  bool IsDehoisted() { return IsDehoistedField::decode(bit_field_); }
6115
  void SetDehoisted(bool is_dehoisted) {
6116
    bit_field_ = IsDehoistedField::update(bit_field_, is_dehoisted);
6117
  }
6118
  ElementsKind elements_kind() const {
6119
    return ElementsKindField::decode(bit_field_);
6120
  }
6121
  LoadKeyedHoleMode hole_mode() const {
6122
    return HoleModeField::decode(bit_field_);
6123
  }
6124

    
6125
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6126
    // kind_fast:       tagged[int32] (none)
6127
    // kind_double:     tagged[int32] (none)
6128
    // kind_external: external[int32] (none)
6129
    if (index == 0) {
6130
      return is_external() ? Representation::External()
6131
          : Representation::Tagged();
6132
    }
6133
    if (index == 1) {
6134
      return ArrayInstructionInterface::KeyedAccessIndexRequirement(
6135
          OperandAt(1)->representation());
6136
    }
6137
    return Representation::None();
6138
  }
6139

    
6140
  virtual Representation observed_input_representation(int index) V8_OVERRIDE {
6141
    return RequiredInputRepresentation(index);
6142
  }
6143

    
6144
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6145

    
6146
  bool UsesMustHandleHole() const;
6147
  bool AllUsesCanTreatHoleAsNaN() const;
6148
  bool RequiresHoleCheck() const;
6149

    
6150
  virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
6151

    
6152
  DECLARE_CONCRETE_INSTRUCTION(LoadKeyed)
6153

    
6154
 protected:
6155
  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
6156
    if (!other->IsLoadKeyed()) return false;
6157
    HLoadKeyed* other_load = HLoadKeyed::cast(other);
6158

    
6159
    if (IsDehoisted() && index_offset() != other_load->index_offset())
6160
      return false;
6161
    return elements_kind() == other_load->elements_kind();
6162
  }
6163

    
6164
 private:
6165
  HLoadKeyed(HValue* obj,
6166
             HValue* key,
6167
             HValue* dependency,
6168
             ElementsKind elements_kind,
6169
             LoadKeyedHoleMode mode = NEVER_RETURN_HOLE)
6170
      : bit_field_(0) {
6171
    bit_field_ = ElementsKindField::encode(elements_kind) |
6172
        HoleModeField::encode(mode);
6173

    
6174
    SetOperandAt(0, obj);
6175
    SetOperandAt(1, key);
6176
    SetOperandAt(2, dependency != NULL ? dependency : obj);
6177

    
6178
    if (!is_external()) {
6179
      // I can detect the case between storing double (holey and fast) and
6180
      // smi/object by looking at elements_kind_.
6181
      ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) ||
6182
             IsFastDoubleElementsKind(elements_kind));
6183

    
6184
      if (IsFastSmiOrObjectElementsKind(elements_kind)) {
6185
        if (IsFastSmiElementsKind(elements_kind) &&
6186
            (!IsHoleyElementsKind(elements_kind) ||
6187
             mode == NEVER_RETURN_HOLE)) {
6188
          set_type(HType::Smi());
6189
          set_representation(Representation::Smi());
6190
        } else {
6191
          set_representation(Representation::Tagged());
6192
        }
6193

    
6194
        SetGVNFlag(kDependsOnArrayElements);
6195
      } else {
6196
        set_representation(Representation::Double());
6197
        SetGVNFlag(kDependsOnDoubleArrayElements);
6198
      }
6199
    } else {
6200
      if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
6201
          elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
6202
        set_representation(Representation::Double());
6203
      } else {
6204
        set_representation(Representation::Integer32());
6205
      }
6206

    
6207
      SetGVNFlag(kDependsOnExternalMemory);
6208
      // Native code could change the specialized array.
6209
      SetGVNFlag(kDependsOnCalls);
6210
    }
6211

    
6212
    SetFlag(kUseGVN);
6213
  }
6214

    
6215
  virtual bool IsDeletable() const V8_OVERRIDE {
6216
    return !RequiresHoleCheck();
6217
  }
6218

    
6219
  // Establish some checks around our packed fields
6220
  enum LoadKeyedBits {
6221
    kBitsForElementsKind = 5,
6222
    kBitsForHoleMode = 1,
6223
    kBitsForIndexOffset = 25,
6224
    kBitsForIsDehoisted = 1,
6225

    
6226
    kStartElementsKind = 0,
6227
    kStartHoleMode = kStartElementsKind + kBitsForElementsKind,
6228
    kStartIndexOffset = kStartHoleMode + kBitsForHoleMode,
6229
    kStartIsDehoisted = kStartIndexOffset + kBitsForIndexOffset
6230
  };
6231

    
6232
  STATIC_ASSERT((kBitsForElementsKind + kBitsForIndexOffset +
6233
                 kBitsForIsDehoisted) <= sizeof(uint32_t)*8);
6234
  STATIC_ASSERT(kElementsKindCount <= (1 << kBitsForElementsKind));
6235
  class ElementsKindField:
6236
    public BitField<ElementsKind, kStartElementsKind, kBitsForElementsKind>
6237
    {};  // NOLINT
6238
  class HoleModeField:
6239
    public BitField<LoadKeyedHoleMode, kStartHoleMode, kBitsForHoleMode>
6240
    {};  // NOLINT
6241
  class IndexOffsetField:
6242
    public BitField<uint32_t, kStartIndexOffset, kBitsForIndexOffset>
6243
    {};  // NOLINT
6244
  class IsDehoistedField:
6245
    public BitField<bool, kStartIsDehoisted, kBitsForIsDehoisted>
6246
    {};  // NOLINT
6247
  uint32_t bit_field_;
6248
};
6249

    
6250

    
6251
class HLoadKeyedGeneric V8_FINAL : public HTemplateInstruction<3> {
6252
 public:
6253
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HLoadKeyedGeneric, HValue*,
6254
                                              HValue*);
6255
  HValue* object() { return OperandAt(0); }
6256
  HValue* key() { return OperandAt(1); }
6257
  HValue* context() { return OperandAt(2); }
6258

    
6259
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6260

    
6261
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6262
    // tagged[tagged]
6263
    return Representation::Tagged();
6264
  }
6265

    
6266
  virtual HValue* Canonicalize() V8_OVERRIDE;
6267

    
6268
  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric)
6269

    
6270
 private:
6271
  HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key) {
6272
    set_representation(Representation::Tagged());
6273
    SetOperandAt(0, obj);
6274
    SetOperandAt(1, key);
6275
    SetOperandAt(2, context);
6276
    SetAllSideEffects();
6277
  }
6278
};
6279

    
6280

    
6281
class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> {
6282
 public:
6283
  DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*,
6284
                                 HObjectAccess, HValue*);
6285

    
6286
  DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
6287

    
6288
  virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE {
6289
    return index == 1;
6290
  }
6291
  virtual bool HasOutOfBoundsAccess(int size) V8_OVERRIDE {
6292
    return !access().IsInobject() || access().offset() >= size;
6293
  }
6294
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6295
    if (index == 0 && access().IsExternalMemory()) {
6296
      // object must be external in case of external memory access
6297
      return Representation::External();
6298
    } else if (index == 1) {
6299
      if (field_representation().IsByte() ||
6300
          field_representation().IsInteger32()) {
6301
        return Representation::Integer32();
6302
      } else if (field_representation().IsDouble() ||
6303
                 field_representation().IsSmi()) {
6304
        return field_representation();
6305
      }
6306
    }
6307
    return Representation::Tagged();
6308
  }
6309
  virtual void HandleSideEffectDominator(GVNFlag side_effect,
6310
                                         HValue* dominator) V8_OVERRIDE {
6311
    ASSERT(side_effect == kChangesNewSpacePromotion);
6312
    new_space_dominator_ = dominator;
6313
  }
6314
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6315

    
6316
  void SkipWriteBarrier() { write_barrier_mode_ = SKIP_WRITE_BARRIER; }
6317
  bool IsSkipWriteBarrier() const {
6318
    return write_barrier_mode_ == SKIP_WRITE_BARRIER;
6319
  }
6320

    
6321
  HValue* object() const { return OperandAt(0); }
6322
  HValue* value() const { return OperandAt(1); }
6323
  HValue* transition() const { return OperandAt(2); }
6324

    
6325
  HObjectAccess access() const { return access_; }
6326
  HValue* new_space_dominator() const { return new_space_dominator_; }
6327
  bool has_transition() const { return has_transition_; }
6328

    
6329
  Handle<Map> transition_map() const {
6330
    if (has_transition()) {
6331
      return Handle<Map>::cast(
6332
          HConstant::cast(transition())->handle(Isolate::Current()));
6333
    } else {
6334
      return Handle<Map>();
6335
    }
6336
  }
6337

    
6338
  void SetTransition(HConstant* map_constant, CompilationInfo* info) {
6339
    ASSERT(!has_transition());  // Only set once.
6340
    Handle<Map> map = Handle<Map>::cast(map_constant->handle(info->isolate()));
6341
    if (map->CanBeDeprecated()) {
6342
      map->AddDependentCompilationInfo(DependentCode::kTransitionGroup, info);
6343
    }
6344
    SetOperandAt(2, map_constant);
6345
    has_transition_ = true;
6346
  }
6347

    
6348
  bool NeedsWriteBarrier() {
6349
    ASSERT(!(FLAG_track_double_fields && field_representation().IsDouble()) ||
6350
           !has_transition());
6351
    if (IsSkipWriteBarrier()) return false;
6352
    if (field_representation().IsDouble()) return false;
6353
    if (field_representation().IsSmi()) return false;
6354
    if (field_representation().IsInteger32()) return false;
6355
    if (field_representation().IsExternal()) return false;
6356
    return StoringValueNeedsWriteBarrier(value()) &&
6357
        ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
6358
  }
6359

    
6360
  bool NeedsWriteBarrierForMap() {
6361
    if (IsSkipWriteBarrier()) return false;
6362
    return ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
6363
  }
6364

    
6365
  Representation field_representation() const {
6366
    return access_.representation();
6367
  }
6368

    
6369
  void UpdateValue(HValue* value) {
6370
    SetOperandAt(1, value);
6371
  }
6372

    
6373
 private:
6374
  HStoreNamedField(HValue* obj,
6375
                   HObjectAccess access,
6376
                   HValue* val)
6377
      : access_(access),
6378
        new_space_dominator_(NULL),
6379
        write_barrier_mode_(UPDATE_WRITE_BARRIER),
6380
        has_transition_(false) {
6381
    SetOperandAt(0, obj);
6382
    SetOperandAt(1, val);
6383
    SetOperandAt(2, obj);
6384
    access.SetGVNFlags(this, true);
6385
  }
6386

    
6387
  HObjectAccess access_;
6388
  HValue* new_space_dominator_;
6389
  WriteBarrierMode write_barrier_mode_ : 1;
6390
  bool has_transition_ : 1;
6391
};
6392

    
6393

    
6394
class HStoreNamedGeneric V8_FINAL : public HTemplateInstruction<3> {
6395
 public:
6396
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HStoreNamedGeneric, HValue*,
6397
                                              Handle<String>, HValue*,
6398
                                              StrictModeFlag);
6399
  HValue* object() { return OperandAt(0); }
6400
  HValue* value() { return OperandAt(1); }
6401
  HValue* context() { return OperandAt(2); }
6402
  Handle<String> name() { return name_; }
6403
  StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
6404

    
6405
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6406

    
6407
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6408
    return Representation::Tagged();
6409
  }
6410

    
6411
  DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric)
6412

    
6413
 private:
6414
  HStoreNamedGeneric(HValue* context,
6415
                     HValue* object,
6416
                     Handle<String> name,
6417
                     HValue* value,
6418
                     StrictModeFlag strict_mode_flag)
6419
      : name_(name),
6420
        strict_mode_flag_(strict_mode_flag) {
6421
    SetOperandAt(0, object);
6422
    SetOperandAt(1, value);
6423
    SetOperandAt(2, context);
6424
    SetAllSideEffects();
6425
  }
6426

    
6427
  Handle<String> name_;
6428
  StrictModeFlag strict_mode_flag_;
6429
};
6430

    
6431

    
6432
class HStoreKeyed V8_FINAL
6433
    : public HTemplateInstruction<3>, public ArrayInstructionInterface {
6434
 public:
6435
  DECLARE_INSTRUCTION_FACTORY_P4(HStoreKeyed, HValue*, HValue*, HValue*,
6436
                                 ElementsKind);
6437

    
6438
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6439
    // kind_fast:       tagged[int32] = tagged
6440
    // kind_double:     tagged[int32] = double
6441
    // kind_smi   :     tagged[int32] = smi
6442
    // kind_external: external[int32] = (double | int32)
6443
    if (index == 0) {
6444
      return is_external() ? Representation::External()
6445
                           : Representation::Tagged();
6446
    } else if (index == 1) {
6447
      return ArrayInstructionInterface::KeyedAccessIndexRequirement(
6448
          OperandAt(1)->representation());
6449
    }
6450

    
6451
    ASSERT_EQ(index, 2);
6452
    if (IsDoubleOrFloatElementsKind(elements_kind())) {
6453
      return Representation::Double();
6454
    }
6455

    
6456
    if (IsFastSmiElementsKind(elements_kind())) {
6457
      return Representation::Smi();
6458
    }
6459

    
6460
    return is_external() ? Representation::Integer32()
6461
                         : Representation::Tagged();
6462
  }
6463

    
6464
  bool is_external() const {
6465
    return IsExternalArrayElementsKind(elements_kind());
6466
  }
6467

    
6468
  virtual Representation observed_input_representation(int index) V8_OVERRIDE {
6469
    if (index < 2) return RequiredInputRepresentation(index);
6470
    if (IsUninitialized()) {
6471
      return Representation::None();
6472
    }
6473
    if (IsFastSmiElementsKind(elements_kind())) {
6474
      return Representation::Smi();
6475
    }
6476
    if (IsDoubleOrFloatElementsKind(elements_kind())) {
6477
      return Representation::Double();
6478
    }
6479
    if (is_external()) {
6480
      return Representation::Integer32();
6481
    }
6482
    // For fast object elements kinds, don't assume anything.
6483
    return Representation::None();
6484
  }
6485

    
6486
  HValue* elements() { return OperandAt(0); }
6487
  HValue* key() { return OperandAt(1); }
6488
  HValue* value() { return OperandAt(2); }
6489
  bool value_is_smi() const {
6490
    return IsFastSmiElementsKind(elements_kind_);
6491
  }
6492
  ElementsKind elements_kind() const { return elements_kind_; }
6493
  uint32_t index_offset() { return index_offset_; }
6494
  void SetIndexOffset(uint32_t index_offset) { index_offset_ = index_offset; }
6495
  HValue* GetKey() { return key(); }
6496
  void SetKey(HValue* key) { SetOperandAt(1, key); }
6497
  bool IsDehoisted() { return is_dehoisted_; }
6498
  void SetDehoisted(bool is_dehoisted) { is_dehoisted_ = is_dehoisted; }
6499
  bool IsUninitialized() { return is_uninitialized_; }
6500
  void SetUninitialized(bool is_uninitialized) {
6501
    is_uninitialized_ = is_uninitialized;
6502
  }
6503

    
6504
  bool IsConstantHoleStore() {
6505
    return value()->IsConstant() && HConstant::cast(value())->IsTheHole();
6506
  }
6507

    
6508
  virtual void HandleSideEffectDominator(GVNFlag side_effect,
6509
                                         HValue* dominator) V8_OVERRIDE {
6510
    ASSERT(side_effect == kChangesNewSpacePromotion);
6511
    new_space_dominator_ = dominator;
6512
  }
6513

    
6514
  HValue* new_space_dominator() const { return new_space_dominator_; }
6515

    
6516
  bool NeedsWriteBarrier() {
6517
    if (value_is_smi()) {
6518
      return false;
6519
    } else {
6520
      return StoringValueNeedsWriteBarrier(value()) &&
6521
          ReceiverObjectNeedsWriteBarrier(elements(), new_space_dominator());
6522
    }
6523
  }
6524

    
6525
  bool NeedsCanonicalization();
6526

    
6527
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6528

    
6529
  DECLARE_CONCRETE_INSTRUCTION(StoreKeyed)
6530

    
6531
 private:
6532
  HStoreKeyed(HValue* obj, HValue* key, HValue* val,
6533
              ElementsKind elements_kind)
6534
      : elements_kind_(elements_kind),
6535
      index_offset_(0),
6536
      is_dehoisted_(false),
6537
      is_uninitialized_(false),
6538
      new_space_dominator_(NULL) {
6539
    SetOperandAt(0, obj);
6540
    SetOperandAt(1, key);
6541
    SetOperandAt(2, val);
6542

    
6543
    if (IsFastObjectElementsKind(elements_kind)) {
6544
      SetFlag(kTrackSideEffectDominators);
6545
      SetGVNFlag(kDependsOnNewSpacePromotion);
6546
    }
6547
    if (is_external()) {
6548
      SetGVNFlag(kChangesExternalMemory);
6549
      SetFlag(kAllowUndefinedAsNaN);
6550
    } else if (IsFastDoubleElementsKind(elements_kind)) {
6551
      SetGVNFlag(kChangesDoubleArrayElements);
6552
    } else if (IsFastSmiElementsKind(elements_kind)) {
6553
      SetGVNFlag(kChangesArrayElements);
6554
    } else {
6555
      SetGVNFlag(kChangesArrayElements);
6556
    }
6557

    
6558
    // EXTERNAL_{UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
6559
    if (elements_kind >= EXTERNAL_BYTE_ELEMENTS &&
6560
        elements_kind <= EXTERNAL_UNSIGNED_INT_ELEMENTS) {
6561
      SetFlag(kTruncatingToInt32);
6562
    }
6563
  }
6564

    
6565
  ElementsKind elements_kind_;
6566
  uint32_t index_offset_;
6567
  bool is_dehoisted_ : 1;
6568
  bool is_uninitialized_ : 1;
6569
  HValue* new_space_dominator_;
6570
};
6571

    
6572

    
6573
class HStoreKeyedGeneric V8_FINAL : public HTemplateInstruction<4> {
6574
 public:
6575
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HStoreKeyedGeneric, HValue*,
6576
                                              HValue*, HValue*, StrictModeFlag);
6577

    
6578
  HValue* object() { return OperandAt(0); }
6579
  HValue* key() { return OperandAt(1); }
6580
  HValue* value() { return OperandAt(2); }
6581
  HValue* context() { return OperandAt(3); }
6582
  StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
6583

    
6584
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6585
    // tagged[tagged] = tagged
6586
    return Representation::Tagged();
6587
  }
6588

    
6589
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6590

    
6591
  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric)
6592

    
6593
 private:
6594
  HStoreKeyedGeneric(HValue* context,
6595
                     HValue* object,
6596
                     HValue* key,
6597
                     HValue* value,
6598
                     StrictModeFlag strict_mode_flag)
6599
      : strict_mode_flag_(strict_mode_flag) {
6600
    SetOperandAt(0, object);
6601
    SetOperandAt(1, key);
6602
    SetOperandAt(2, value);
6603
    SetOperandAt(3, context);
6604
    SetAllSideEffects();
6605
  }
6606

    
6607
  StrictModeFlag strict_mode_flag_;
6608
};
6609

    
6610

    
6611
class HTransitionElementsKind V8_FINAL : public HTemplateInstruction<2> {
6612
 public:
6613
  inline static HTransitionElementsKind* New(Zone* zone,
6614
                                             HValue* context,
6615
                                             HValue* object,
6616
                                             Handle<Map> original_map,
6617
                                             Handle<Map> transitioned_map) {
6618
    return new(zone) HTransitionElementsKind(context, object,
6619
                                             original_map, transitioned_map);
6620
  }
6621

    
6622
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6623
    return Representation::Tagged();
6624
  }
6625

    
6626
  HValue* object() { return OperandAt(0); }
6627
  HValue* context() { return OperandAt(1); }
6628
  Unique<Map> original_map() { return original_map_; }
6629
  Unique<Map> transitioned_map() { return transitioned_map_; }
6630
  ElementsKind from_kind() { return from_kind_; }
6631
  ElementsKind to_kind() { return to_kind_; }
6632

    
6633
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6634

    
6635
  DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
6636

    
6637
 protected:
6638
  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
6639
    HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
6640
    return original_map_ == instr->original_map_ &&
6641
           transitioned_map_ == instr->transitioned_map_;
6642
  }
6643

    
6644
 private:
6645
  HTransitionElementsKind(HValue* context,
6646
                          HValue* object,
6647
                          Handle<Map> original_map,
6648
                          Handle<Map> transitioned_map)
6649
      : original_map_(Unique<Map>(original_map)),
6650
        transitioned_map_(Unique<Map>(transitioned_map)),
6651
        from_kind_(original_map->elements_kind()),
6652
        to_kind_(transitioned_map->elements_kind()) {
6653
    SetOperandAt(0, object);
6654
    SetOperandAt(1, context);
6655
    SetFlag(kUseGVN);
6656
    SetGVNFlag(kChangesElementsKind);
6657
    if (!IsSimpleMapChangeTransition(from_kind_, to_kind_)) {
6658
      SetGVNFlag(kChangesElementsPointer);
6659
      SetGVNFlag(kChangesNewSpacePromotion);
6660
    }
6661
    set_representation(Representation::Tagged());
6662
  }
6663

    
6664
  Unique<Map> original_map_;
6665
  Unique<Map> transitioned_map_;
6666
  ElementsKind from_kind_;
6667
  ElementsKind to_kind_;
6668
};
6669

    
6670

    
6671
class HStringAdd V8_FINAL : public HBinaryOperation {
6672
 public:
6673
  static HInstruction* New(Zone* zone,
6674
                           HValue* context,
6675
                           HValue* left,
6676
                           HValue* right,
6677
                           StringAddFlags flags = STRING_ADD_CHECK_NONE);
6678

    
6679
  StringAddFlags flags() const { return flags_; }
6680

    
6681
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6682
    return Representation::Tagged();
6683
  }
6684

    
6685
  DECLARE_CONCRETE_INSTRUCTION(StringAdd)
6686

    
6687
 protected:
6688
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
6689

    
6690
 private:
6691
  HStringAdd(HValue* context, HValue* left, HValue* right, StringAddFlags flags)
6692
      : HBinaryOperation(context, left, right, HType::String()), flags_(flags) {
6693
    set_representation(Representation::Tagged());
6694
    if (MightHaveSideEffects()) {
6695
      SetAllSideEffects();
6696
    } else {
6697
      SetFlag(kUseGVN);
6698
      SetGVNFlag(kDependsOnMaps);
6699
      SetGVNFlag(kChangesNewSpacePromotion);
6700
    }
6701
  }
6702

    
6703
  bool MightHaveSideEffects() const {
6704
    return flags_ != STRING_ADD_CHECK_NONE &&
6705
      (left()->ToStringCanBeObserved() || right()->ToStringCanBeObserved());
6706
  }
6707

    
6708
  // No side-effects except possible allocation:
6709
  // NOTE: this instruction does not call ToString() on its inputs, when flags_
6710
  // is set to STRING_ADD_CHECK_NONE.
6711
  virtual bool IsDeletable() const V8_OVERRIDE {
6712
    return !MightHaveSideEffects();
6713
  }
6714

    
6715
  const StringAddFlags flags_;
6716
};
6717

    
6718

    
6719
class HStringCharCodeAt V8_FINAL : public HTemplateInstruction<3> {
6720
 public:
6721
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HStringCharCodeAt,
6722
                                              HValue*,
6723
                                              HValue*);
6724

    
6725
  virtual Representation RequiredInputRepresentation(int index) {
6726
    // The index is supposed to be Integer32.
6727
    return index == 2
6728
        ? Representation::Integer32()
6729
        : Representation::Tagged();
6730
  }
6731

    
6732
  HValue* context() const { return OperandAt(0); }
6733
  HValue* string() const { return OperandAt(1); }
6734
  HValue* index() const { return OperandAt(2); }
6735

    
6736
  DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt)
6737

    
6738
 protected:
6739
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
6740

    
6741
  virtual Range* InferRange(Zone* zone) V8_OVERRIDE {
6742
    return new(zone) Range(0, String::kMaxUtf16CodeUnit);
6743
  }
6744

    
6745
 private:
6746
  HStringCharCodeAt(HValue* context, HValue* string, HValue* index) {
6747
    SetOperandAt(0, context);
6748
    SetOperandAt(1, string);
6749
    SetOperandAt(2, index);
6750
    set_representation(Representation::Integer32());
6751
    SetFlag(kUseGVN);
6752
    SetGVNFlag(kDependsOnMaps);
6753
    SetGVNFlag(kChangesNewSpacePromotion);
6754
  }
6755

    
6756
  // No side effects: runtime function assumes string + number inputs.
6757
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
6758
};
6759

    
6760

    
6761
class HStringCharFromCode V8_FINAL : public HTemplateInstruction<2> {
6762
 public:
6763
  static HInstruction* New(Zone* zone,
6764
                           HValue* context,
6765
                           HValue* char_code);
6766

    
6767
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6768
    return index == 0
6769
        ? Representation::Tagged()
6770
        : Representation::Integer32();
6771
  }
6772

    
6773
  HValue* context() const { return OperandAt(0); }
6774
  HValue* value() const { return OperandAt(1); }
6775

    
6776
  virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
6777

    
6778
  DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode)
6779

    
6780
 private:
6781
  HStringCharFromCode(HValue* context, HValue* char_code)
6782
      : HTemplateInstruction<2>(HType::String()) {
6783
    SetOperandAt(0, context);
6784
    SetOperandAt(1, char_code);
6785
    set_representation(Representation::Tagged());
6786
    SetFlag(kUseGVN);
6787
    SetGVNFlag(kChangesNewSpacePromotion);
6788
  }
6789

    
6790
  virtual bool IsDeletable() const V8_OVERRIDE {
6791
    return !value()->ToNumberCanBeObserved();
6792
  }
6793
};
6794

    
6795

    
6796
template <int V>
6797
class HMaterializedLiteral : public HTemplateInstruction<V> {
6798
 public:
6799
  HMaterializedLiteral<V>(int index, int depth, AllocationSiteMode mode)
6800
      : literal_index_(index), depth_(depth), allocation_site_mode_(mode) {
6801
    this->set_representation(Representation::Tagged());
6802
  }
6803

    
6804
  HMaterializedLiteral<V>(int index, int depth)
6805
      : literal_index_(index), depth_(depth),
6806
        allocation_site_mode_(DONT_TRACK_ALLOCATION_SITE) {
6807
    this->set_representation(Representation::Tagged());
6808
  }
6809

    
6810
  int literal_index() const { return literal_index_; }
6811
  int depth() const { return depth_; }
6812
  AllocationSiteMode allocation_site_mode() const {
6813
    return allocation_site_mode_;
6814
  }
6815

    
6816
 private:
6817
  virtual bool IsDeletable() const V8_FINAL V8_OVERRIDE { return true; }
6818

    
6819
  int literal_index_;
6820
  int depth_;
6821
  AllocationSiteMode allocation_site_mode_;
6822
};
6823

    
6824

    
6825
class HRegExpLiteral V8_FINAL : public HMaterializedLiteral<1> {
6826
 public:
6827
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HRegExpLiteral,
6828
                                              Handle<FixedArray>,
6829
                                              Handle<String>,
6830
                                              Handle<String>,
6831
                                              int);
6832

    
6833
  HValue* context() { return OperandAt(0); }
6834
  Handle<FixedArray> literals() { return literals_; }
6835
  Handle<String> pattern() { return pattern_; }
6836
  Handle<String> flags() { return flags_; }
6837

    
6838
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6839
    return Representation::Tagged();
6840
  }
6841

    
6842
  DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral)
6843

    
6844
 private:
6845
  HRegExpLiteral(HValue* context,
6846
                 Handle<FixedArray> literals,
6847
                 Handle<String> pattern,
6848
                 Handle<String> flags,
6849
                 int literal_index)
6850
      : HMaterializedLiteral<1>(literal_index, 0),
6851
        literals_(literals),
6852
        pattern_(pattern),
6853
        flags_(flags) {
6854
    SetOperandAt(0, context);
6855
    SetAllSideEffects();
6856
    set_type(HType::JSObject());
6857
  }
6858

    
6859
  Handle<FixedArray> literals_;
6860
  Handle<String> pattern_;
6861
  Handle<String> flags_;
6862
};
6863

    
6864

    
6865
class HFunctionLiteral V8_FINAL : public HTemplateInstruction<1> {
6866
 public:
6867
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HFunctionLiteral,
6868
                                              Handle<SharedFunctionInfo>,
6869
                                              bool);
6870
  HValue* context() { return OperandAt(0); }
6871

    
6872
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6873
    return Representation::Tagged();
6874
  }
6875

    
6876
  DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral)
6877

    
6878
  Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
6879
  bool pretenure() const { return pretenure_; }
6880
  bool has_no_literals() const { return has_no_literals_; }
6881
  bool is_generator() const { return is_generator_; }
6882
  LanguageMode language_mode() const { return language_mode_; }
6883

    
6884
 private:
6885
  HFunctionLiteral(HValue* context,
6886
                   Handle<SharedFunctionInfo> shared,
6887
                   bool pretenure)
6888
      : HTemplateInstruction<1>(HType::JSObject()),
6889
        shared_info_(shared),
6890
        pretenure_(pretenure),
6891
        has_no_literals_(shared->num_literals() == 0),
6892
        is_generator_(shared->is_generator()),
6893
        language_mode_(shared->language_mode()) {
6894
    SetOperandAt(0, context);
6895
    set_representation(Representation::Tagged());
6896
    SetGVNFlag(kChangesNewSpacePromotion);
6897
  }
6898

    
6899
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
6900

    
6901
  Handle<SharedFunctionInfo> shared_info_;
6902
  bool pretenure_ : 1;
6903
  bool has_no_literals_ : 1;
6904
  bool is_generator_ : 1;
6905
  LanguageMode language_mode_;
6906
};
6907

    
6908

    
6909
class HTypeof V8_FINAL : public HTemplateInstruction<2> {
6910
 public:
6911
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HTypeof, HValue*);
6912

    
6913
  HValue* context() { return OperandAt(0); }
6914
  HValue* value() { return OperandAt(1); }
6915

    
6916
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
6917

    
6918
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6919
    return Representation::Tagged();
6920
  }
6921

    
6922
  DECLARE_CONCRETE_INSTRUCTION(Typeof)
6923

    
6924
 private:
6925
  explicit HTypeof(HValue* context, HValue* value) {
6926
    SetOperandAt(0, context);
6927
    SetOperandAt(1, value);
6928
    set_representation(Representation::Tagged());
6929
  }
6930

    
6931
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
6932
};
6933

    
6934

    
6935
class HTrapAllocationMemento V8_FINAL : public HTemplateInstruction<1> {
6936
 public:
6937
  DECLARE_INSTRUCTION_FACTORY_P1(HTrapAllocationMemento, HValue*);
6938

    
6939
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6940
    return Representation::Tagged();
6941
  }
6942

    
6943
  HValue* object() { return OperandAt(0); }
6944

    
6945
  DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento)
6946

    
6947
 private:
6948
  explicit HTrapAllocationMemento(HValue* obj) {
6949
    SetOperandAt(0, obj);
6950
  }
6951
};
6952

    
6953

    
6954
class HToFastProperties V8_FINAL : public HUnaryOperation {
6955
 public:
6956
  DECLARE_INSTRUCTION_FACTORY_P1(HToFastProperties, HValue*);
6957

    
6958
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6959
    return Representation::Tagged();
6960
  }
6961

    
6962
  DECLARE_CONCRETE_INSTRUCTION(ToFastProperties)
6963

    
6964
 private:
6965
  explicit HToFastProperties(HValue* value) : HUnaryOperation(value) {
6966
    set_representation(Representation::Tagged());
6967
    SetGVNFlag(kChangesNewSpacePromotion);
6968

    
6969
    // This instruction is not marked as kChangesMaps, but does
6970
    // change the map of the input operand. Use it only when creating
6971
    // object literals via a runtime call.
6972
    ASSERT(value->IsCallRuntime());
6973
#ifdef DEBUG
6974
    const Runtime::Function* function = HCallRuntime::cast(value)->function();
6975
    ASSERT(function->function_id == Runtime::kCreateObjectLiteral);
6976
#endif
6977
  }
6978

    
6979
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
6980
};
6981

    
6982

    
6983
class HValueOf V8_FINAL : public HUnaryOperation {
6984
 public:
6985
  DECLARE_INSTRUCTION_FACTORY_P1(HValueOf, HValue*);
6986

    
6987
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
6988
    return Representation::Tagged();
6989
  }
6990

    
6991
  DECLARE_CONCRETE_INSTRUCTION(ValueOf)
6992

    
6993
 private:
6994
  explicit HValueOf(HValue* value) : HUnaryOperation(value) {
6995
    set_representation(Representation::Tagged());
6996
  }
6997

    
6998
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
6999
};
7000

    
7001

    
7002
class HDateField V8_FINAL : public HUnaryOperation {
7003
 public:
7004
  DECLARE_INSTRUCTION_FACTORY_P2(HDateField, HValue*, Smi*);
7005

    
7006
  Smi* index() const { return index_; }
7007

    
7008
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7009
    return Representation::Tagged();
7010
  }
7011

    
7012
  DECLARE_CONCRETE_INSTRUCTION(DateField)
7013

    
7014
 private:
7015
  HDateField(HValue* date, Smi* index)
7016
      : HUnaryOperation(date), index_(index) {
7017
    set_representation(Representation::Tagged());
7018
  }
7019

    
7020
  Smi* index_;
7021
};
7022

    
7023

    
7024
class HSeqStringSetChar V8_FINAL : public HTemplateInstruction<3> {
7025
 public:
7026
  DECLARE_INSTRUCTION_FACTORY_P4(HSeqStringSetChar, String::Encoding,
7027
                                 HValue*, HValue*, HValue*);
7028

    
7029
  String::Encoding encoding() { return encoding_; }
7030
  HValue* string() { return OperandAt(0); }
7031
  HValue* index() { return OperandAt(1); }
7032
  HValue* value() { return OperandAt(2); }
7033

    
7034
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7035
    return (index == 0) ? Representation::Tagged()
7036
                        : Representation::Integer32();
7037
  }
7038

    
7039
  DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar)
7040

    
7041
 private:
7042
  HSeqStringSetChar(String::Encoding encoding,
7043
                    HValue* string,
7044
                    HValue* index,
7045
                    HValue* value) : encoding_(encoding) {
7046
    SetOperandAt(0, string);
7047
    SetOperandAt(1, index);
7048
    SetOperandAt(2, value);
7049
    set_representation(Representation::Tagged());
7050
  }
7051

    
7052
  String::Encoding encoding_;
7053
};
7054

    
7055

    
7056
class HCheckMapValue V8_FINAL : public HTemplateInstruction<2> {
7057
 public:
7058
  DECLARE_INSTRUCTION_FACTORY_P2(HCheckMapValue, HValue*, HValue*);
7059

    
7060
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7061
    return Representation::Tagged();
7062
  }
7063

    
7064
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7065

    
7066
  virtual HType CalculateInferredType() V8_OVERRIDE {
7067
    return HType::Tagged();
7068
  }
7069

    
7070
  HValue* value() { return OperandAt(0); }
7071
  HValue* map() { return OperandAt(1); }
7072

    
7073
  DECLARE_CONCRETE_INSTRUCTION(CheckMapValue)
7074

    
7075
 protected:
7076
  virtual bool DataEquals(HValue* other) V8_OVERRIDE {
7077
    return true;
7078
  }
7079

    
7080
 private:
7081
  HCheckMapValue(HValue* value,
7082
                 HValue* map) {
7083
    SetOperandAt(0, value);
7084
    SetOperandAt(1, map);
7085
    set_representation(Representation::Tagged());
7086
    SetFlag(kUseGVN);
7087
    SetGVNFlag(kDependsOnMaps);
7088
    SetGVNFlag(kDependsOnElementsKind);
7089
  }
7090
};
7091

    
7092

    
7093
class HForInPrepareMap V8_FINAL : public HTemplateInstruction<2> {
7094
 public:
7095
  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P1(HForInPrepareMap, HValue*);
7096

    
7097
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7098
    return Representation::Tagged();
7099
  }
7100

    
7101
  HValue* context() { return OperandAt(0); }
7102
  HValue* enumerable() { return OperandAt(1); }
7103

    
7104
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7105

    
7106
  virtual HType CalculateInferredType() V8_OVERRIDE {
7107
    return HType::Tagged();
7108
  }
7109

    
7110
  DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap);
7111

    
7112
 private:
7113
  HForInPrepareMap(HValue* context,
7114
                   HValue* object) {
7115
    SetOperandAt(0, context);
7116
    SetOperandAt(1, object);
7117
    set_representation(Representation::Tagged());
7118
    SetAllSideEffects();
7119
  }
7120
};
7121

    
7122

    
7123
class HForInCacheArray V8_FINAL : public HTemplateInstruction<2> {
7124
 public:
7125
  DECLARE_INSTRUCTION_FACTORY_P3(HForInCacheArray, HValue*, HValue*, int);
7126

    
7127
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7128
    return Representation::Tagged();
7129
  }
7130

    
7131
  HValue* enumerable() { return OperandAt(0); }
7132
  HValue* map() { return OperandAt(1); }
7133
  int idx() { return idx_; }
7134

    
7135
  HForInCacheArray* index_cache() {
7136
    return index_cache_;
7137
  }
7138

    
7139
  void set_index_cache(HForInCacheArray* index_cache) {
7140
    index_cache_ = index_cache;
7141
  }
7142

    
7143
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7144

    
7145
  virtual HType CalculateInferredType() V8_OVERRIDE {
7146
    return HType::Tagged();
7147
  }
7148

    
7149
  DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray);
7150

    
7151
 private:
7152
  HForInCacheArray(HValue* enumerable,
7153
                   HValue* keys,
7154
                   int idx) : idx_(idx) {
7155
    SetOperandAt(0, enumerable);
7156
    SetOperandAt(1, keys);
7157
    set_representation(Representation::Tagged());
7158
  }
7159

    
7160
  int idx_;
7161
  HForInCacheArray* index_cache_;
7162
};
7163

    
7164

    
7165
class HLoadFieldByIndex V8_FINAL : public HTemplateInstruction<2> {
7166
 public:
7167
  HLoadFieldByIndex(HValue* object,
7168
                    HValue* index) {
7169
    SetOperandAt(0, object);
7170
    SetOperandAt(1, index);
7171
    set_representation(Representation::Tagged());
7172
  }
7173

    
7174
  virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
7175
    return Representation::Tagged();
7176
  }
7177

    
7178
  HValue* object() { return OperandAt(0); }
7179
  HValue* index() { return OperandAt(1); }
7180

    
7181
  virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
7182

    
7183
  virtual HType CalculateInferredType() V8_OVERRIDE {
7184
    return HType::Tagged();
7185
  }
7186

    
7187
  DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex);
7188

    
7189
 private:
7190
  virtual bool IsDeletable() const V8_OVERRIDE { return true; }
7191
};
7192

    
7193

    
7194
#undef DECLARE_INSTRUCTION
7195
#undef DECLARE_CONCRETE_INSTRUCTION
7196

    
7197
} }  // namespace v8::internal
7198

    
7199
#endif  // V8_HYDROGEN_INSTRUCTIONS_H_