Fixed Lithium environment generation bug for captured objects (created
[platform/upstream/v8.git] / src / x64 / lithium-x64.h
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_X64_LITHIUM_X64_H_
29 #define V8_X64_LITHIUM_X64_H_
30
31 #include "hydrogen.h"
32 #include "lithium-allocator.h"
33 #include "lithium.h"
34 #include "safepoint-table.h"
35 #include "utils.h"
36
37 namespace v8 {
38 namespace internal {
39
40 // Forward declarations.
41 class LCodeGen;
42
43 #define LITHIUM_CONCRETE_INSTRUCTION_LIST(V)    \
44   V(AccessArgumentsAt)                          \
45   V(AddI)                                       \
46   V(Allocate)                                   \
47   V(ApplyArguments)                             \
48   V(ArgumentsElements)                          \
49   V(ArgumentsLength)                            \
50   V(ArithmeticD)                                \
51   V(ArithmeticT)                                \
52   V(BitI)                                       \
53   V(BoundsCheck)                                \
54   V(Branch)                                     \
55   V(CallConstantFunction)                       \
56   V(CallFunction)                               \
57   V(CallGlobal)                                 \
58   V(CallKeyed)                                  \
59   V(CallKnownGlobal)                            \
60   V(CallNamed)                                  \
61   V(CallNew)                                    \
62   V(CallNewArray)                               \
63   V(CallRuntime)                                \
64   V(CallStub)                                   \
65   V(CheckInstanceType)                          \
66   V(CheckMaps)                                  \
67   V(CheckMapValue)                              \
68   V(CheckNonSmi)                                \
69   V(CheckSmi)                                   \
70   V(CheckValue)                                 \
71   V(ClampDToUint8)                              \
72   V(ClampIToUint8)                              \
73   V(ClampTToUint8)                              \
74   V(ClassOfTestAndBranch)                       \
75   V(CompareMinusZeroAndBranch)                  \
76   V(CompareNumericAndBranch)                    \
77   V(CmpObjectEqAndBranch)                       \
78   V(CmpHoleAndBranch)                           \
79   V(CmpMapAndBranch)                            \
80   V(CmpT)                                       \
81   V(ConstantD)                                  \
82   V(ConstantE)                                  \
83   V(ConstantI)                                  \
84   V(ConstantS)                                  \
85   V(ConstantT)                                  \
86   V(Context)                                    \
87   V(DateField)                                  \
88   V(DebugBreak)                                 \
89   V(DeclareGlobals)                             \
90   V(Deoptimize)                                 \
91   V(DivI)                                       \
92   V(DoubleToI)                                  \
93   V(DoubleToSmi)                                \
94   V(Drop)                                       \
95   V(DummyUse)                                   \
96   V(Dummy)                                      \
97   V(ElementsKind)                               \
98   V(ForInCacheArray)                            \
99   V(ForInPrepareMap)                            \
100   V(FunctionLiteral)                            \
101   V(GetCachedArrayIndex)                        \
102   V(GlobalObject)                               \
103   V(GlobalReceiver)                             \
104   V(Goto)                                       \
105   V(HasCachedArrayIndexAndBranch)               \
106   V(HasInstanceTypeAndBranch)                   \
107   V(InnerAllocatedObject)                       \
108   V(InstanceOf)                                 \
109   V(InstanceOfKnownGlobal)                      \
110   V(InstructionGap)                             \
111   V(Integer32ToDouble)                          \
112   V(Integer32ToSmi)                             \
113   V(InvokeFunction)                             \
114   V(IsConstructCallAndBranch)                   \
115   V(IsObjectAndBranch)                          \
116   V(IsStringAndBranch)                          \
117   V(IsSmiAndBranch)                             \
118   V(IsUndetectableAndBranch)                    \
119   V(Label)                                      \
120   V(LazyBailout)                                \
121   V(LoadContextSlot)                            \
122   V(LoadExternalArrayPointer)                   \
123   V(LoadRoot)                                   \
124   V(LoadFieldByIndex)                           \
125   V(LoadFunctionPrototype)                      \
126   V(LoadGlobalCell)                             \
127   V(LoadGlobalGeneric)                          \
128   V(LoadKeyed)                                  \
129   V(LoadKeyedGeneric)                           \
130   V(LoadNamedField)                             \
131   V(LoadNamedGeneric)                           \
132   V(MapEnumLength)                              \
133   V(MathAbs)                                    \
134   V(MathExp)                                    \
135   V(MathFloor)                                  \
136   V(MathFloorOfDiv)                             \
137   V(MathLog)                                    \
138   V(MathMinMax)                                 \
139   V(MathPowHalf)                                \
140   V(MathRound)                                  \
141   V(MathSqrt)                                   \
142   V(ModI)                                       \
143   V(MulI)                                       \
144   V(NumberTagD)                                 \
145   V(NumberTagI)                                 \
146   V(NumberTagU)                                 \
147   V(NumberUntagD)                               \
148   V(OsrEntry)                                   \
149   V(OuterContext)                               \
150   V(Parameter)                                  \
151   V(Power)                                      \
152   V(PushArgument)                               \
153   V(RegExpLiteral)                              \
154   V(Return)                                     \
155   V(SeqStringGetChar)                           \
156   V(SeqStringSetChar)                           \
157   V(ShiftI)                                     \
158   V(SmiTag)                                     \
159   V(SmiUntag)                                   \
160   V(StackCheck)                                 \
161   V(StoreCodeEntry)                             \
162   V(StoreContextSlot)                           \
163   V(StoreGlobalCell)                            \
164   V(StoreGlobalGeneric)                         \
165   V(StoreKeyed)                                 \
166   V(StoreKeyedGeneric)                          \
167   V(StoreNamedField)                            \
168   V(StoreNamedGeneric)                          \
169   V(StringAdd)                                  \
170   V(StringCharCodeAt)                           \
171   V(StringCharFromCode)                         \
172   V(StringCompareAndBranch)                     \
173   V(SubI)                                       \
174   V(TaggedToI)                                  \
175   V(ThisFunction)                               \
176   V(Throw)                                      \
177   V(ToFastProperties)                           \
178   V(TransitionElementsKind)                     \
179   V(TrapAllocationMemento)                      \
180   V(Typeof)                                     \
181   V(TypeofIsAndBranch)                          \
182   V(Uint32ToDouble)                             \
183   V(Uint32ToSmi)                                \
184   V(UnknownOSRValue)                            \
185   V(ValueOf)                                    \
186   V(WrapReceiver)
187
188
189 #define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic)                        \
190   virtual Opcode opcode() const V8_FINAL V8_OVERRIDE {                      \
191     return LInstruction::k##type;                                           \
192   }                                                                         \
193   virtual void CompileToNative(LCodeGen* generator) V8_FINAL V8_OVERRIDE;   \
194   virtual const char* Mnemonic() const V8_FINAL V8_OVERRIDE {               \
195     return mnemonic;                                                        \
196   }                                                                         \
197   static L##type* cast(LInstruction* instr) {                               \
198     ASSERT(instr->Is##type());                                              \
199     return reinterpret_cast<L##type*>(instr);                               \
200   }
201
202
203 #define DECLARE_HYDROGEN_ACCESSOR(type)     \
204   H##type* hydrogen() const {               \
205     return H##type::cast(hydrogen_value()); \
206   }
207
208
209 class LInstruction : public ZoneObject {
210  public:
211   LInstruction()
212       : environment_(NULL),
213         hydrogen_value_(NULL),
214         bit_field_(IsCallBits::encode(false)) {
215   }
216
217   virtual ~LInstruction() {}
218
219   virtual void CompileToNative(LCodeGen* generator) = 0;
220   virtual const char* Mnemonic() const = 0;
221   virtual void PrintTo(StringStream* stream);
222   virtual void PrintDataTo(StringStream* stream);
223   virtual void PrintOutputOperandTo(StringStream* stream);
224
225   enum Opcode {
226     // Declare a unique enum value for each instruction.
227 #define DECLARE_OPCODE(type) k##type,
228     LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE)
229     kNumberOfInstructions
230 #undef DECLARE_OPCODE
231   };
232
233   virtual Opcode opcode() const = 0;
234
235   // Declare non-virtual type testers for all leaf IR classes.
236 #define DECLARE_PREDICATE(type) \
237   bool Is##type() const { return opcode() == k##type; }
238   LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_PREDICATE)
239 #undef DECLARE_PREDICATE
240
241   // Declare virtual predicates for instructions that don't have
242   // an opcode.
243   virtual bool IsGap() const { return false; }
244
245   virtual bool IsControl() const { return false; }
246
247   void set_environment(LEnvironment* env) { environment_ = env; }
248   LEnvironment* environment() const { return environment_; }
249   bool HasEnvironment() const { return environment_ != NULL; }
250
251   void set_pointer_map(LPointerMap* p) { pointer_map_.set(p); }
252   LPointerMap* pointer_map() const { return pointer_map_.get(); }
253   bool HasPointerMap() const { return pointer_map_.is_set(); }
254
255   void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; }
256   HValue* hydrogen_value() const { return hydrogen_value_; }
257
258   void MarkAsCall() { bit_field_ = IsCallBits::update(bit_field_, true); }
259   bool IsCall() const { return IsCallBits::decode(bit_field_); }
260
261   // Interface to the register allocator and iterators.
262   bool ClobbersTemps() const { return IsCall(); }
263   bool ClobbersRegisters() const { return IsCall(); }
264   virtual bool ClobbersDoubleRegisters() const { return IsCall(); }
265
266   virtual void SetDeferredLazyDeoptimizationEnvironment(LEnvironment* env) { }
267
268   // Interface to the register allocator and iterators.
269   bool IsMarkedAsCall() const { return IsCall(); }
270
271   virtual bool HasResult() const = 0;
272   virtual LOperand* result() const = 0;
273
274   LOperand* FirstInput() { return InputAt(0); }
275   LOperand* Output() { return HasResult() ? result() : NULL; }
276
277   virtual bool HasInterestingComment(LCodeGen* gen) const { return true; }
278
279 #ifdef DEBUG
280   void VerifyCall();
281 #endif
282
283  private:
284   // Iterator support.
285   friend class InputIterator;
286   virtual int InputCount() = 0;
287   virtual LOperand* InputAt(int i) = 0;
288
289   friend class TempIterator;
290   virtual int TempCount() = 0;
291   virtual LOperand* TempAt(int i) = 0;
292
293   class IsCallBits: public BitField<bool, 0, 1> {};
294
295   LEnvironment* environment_;
296   SetOncePointer<LPointerMap> pointer_map_;
297   HValue* hydrogen_value_;
298   int bit_field_;
299 };
300
301
302 // R = number of result operands (0 or 1).
303 // I = number of input operands.
304 // T = number of temporary operands.
305 template<int R, int I, int T>
306 class LTemplateInstruction : public LInstruction {
307  public:
308   // Allow 0 or 1 output operands.
309   STATIC_ASSERT(R == 0 || R == 1);
310   virtual bool HasResult() const V8_FINAL V8_OVERRIDE {
311     return R != 0 && result() != NULL;
312   }
313   void set_result(LOperand* operand) { results_[0] = operand; }
314   LOperand* result() const { return results_[0]; }
315
316  protected:
317   EmbeddedContainer<LOperand*, R> results_;
318   EmbeddedContainer<LOperand*, I> inputs_;
319   EmbeddedContainer<LOperand*, T> temps_;
320
321  private:
322   // Iterator support.
323   virtual int InputCount() V8_FINAL V8_OVERRIDE { return I; }
324   virtual LOperand* InputAt(int i) V8_FINAL V8_OVERRIDE { return inputs_[i]; }
325
326   virtual int TempCount() V8_FINAL V8_OVERRIDE { return T; }
327   virtual LOperand* TempAt(int i) V8_FINAL V8_OVERRIDE { return temps_[i]; }
328 };
329
330
331 class LGap : public LTemplateInstruction<0, 0, 0> {
332  public:
333   explicit LGap(HBasicBlock* block)
334       : block_(block) {
335     parallel_moves_[BEFORE] = NULL;
336     parallel_moves_[START] = NULL;
337     parallel_moves_[END] = NULL;
338     parallel_moves_[AFTER] = NULL;
339   }
340
341   // Can't use the DECLARE-macro here because of sub-classes.
342   virtual bool IsGap() const V8_FINAL V8_OVERRIDE { return true; }
343   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
344   static LGap* cast(LInstruction* instr) {
345     ASSERT(instr->IsGap());
346     return reinterpret_cast<LGap*>(instr);
347   }
348
349   bool IsRedundant() const;
350
351   HBasicBlock* block() const { return block_; }
352
353   enum InnerPosition {
354     BEFORE,
355     START,
356     END,
357     AFTER,
358     FIRST_INNER_POSITION = BEFORE,
359     LAST_INNER_POSITION = AFTER
360   };
361
362   LParallelMove* GetOrCreateParallelMove(InnerPosition pos,
363                                          Zone* zone)  {
364     if (parallel_moves_[pos] == NULL) {
365       parallel_moves_[pos] = new(zone) LParallelMove(zone);
366     }
367     return parallel_moves_[pos];
368   }
369
370   LParallelMove* GetParallelMove(InnerPosition pos)  {
371     return parallel_moves_[pos];
372   }
373
374  private:
375   LParallelMove* parallel_moves_[LAST_INNER_POSITION + 1];
376   HBasicBlock* block_;
377 };
378
379
380 class LInstructionGap V8_FINAL : public LGap {
381  public:
382   explicit LInstructionGap(HBasicBlock* block) : LGap(block) { }
383
384   virtual bool HasInterestingComment(LCodeGen* gen) const V8_OVERRIDE {
385     return !IsRedundant();
386   }
387
388   DECLARE_CONCRETE_INSTRUCTION(InstructionGap, "gap")
389 };
390
391
392 class LGoto V8_FINAL : public LTemplateInstruction<0, 0, 0> {
393  public:
394   explicit LGoto(HBasicBlock* block) : block_(block) { }
395
396   virtual bool HasInterestingComment(LCodeGen* gen) const V8_OVERRIDE;
397   DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
398   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
399   virtual bool IsControl() const V8_OVERRIDE { return true; }
400
401   int block_id() const { return block_->block_id(); }
402
403  private:
404   HBasicBlock* block_;
405 };
406
407
408 class LLazyBailout V8_FINAL : public LTemplateInstruction<0, 0, 0> {
409  public:
410   LLazyBailout() : gap_instructions_size_(0) { }
411
412   DECLARE_CONCRETE_INSTRUCTION(LazyBailout, "lazy-bailout")
413
414   void set_gap_instructions_size(int gap_instructions_size) {
415     gap_instructions_size_ = gap_instructions_size;
416   }
417   int gap_instructions_size() { return gap_instructions_size_; }
418
419  private:
420   int gap_instructions_size_;
421 };
422
423
424 class LDummy V8_FINAL : public LTemplateInstruction<1, 0, 0> {
425  public:
426   explicit LDummy() { }
427   DECLARE_CONCRETE_INSTRUCTION(Dummy, "dummy")
428 };
429
430
431 class LDummyUse V8_FINAL : public LTemplateInstruction<1, 1, 0> {
432  public:
433   explicit LDummyUse(LOperand* value) {
434     inputs_[0] = value;
435   }
436   DECLARE_CONCRETE_INSTRUCTION(DummyUse, "dummy-use")
437 };
438
439
440 class LDeoptimize V8_FINAL : public LTemplateInstruction<0, 0, 0> {
441  public:
442   DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
443   DECLARE_HYDROGEN_ACCESSOR(Deoptimize)
444 };
445
446
447 class LLabel V8_FINAL : public LGap {
448  public:
449   explicit LLabel(HBasicBlock* block)
450       : LGap(block), replacement_(NULL) { }
451
452   virtual bool HasInterestingComment(LCodeGen* gen) const V8_OVERRIDE {
453     return false;
454   }
455   DECLARE_CONCRETE_INSTRUCTION(Label, "label")
456
457   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
458
459   int block_id() const { return block()->block_id(); }
460   bool is_loop_header() const { return block()->IsLoopHeader(); }
461   bool is_osr_entry() const { return block()->is_osr_entry(); }
462   Label* label() { return &label_; }
463   LLabel* replacement() const { return replacement_; }
464   void set_replacement(LLabel* label) { replacement_ = label; }
465   bool HasReplacement() const { return replacement_ != NULL; }
466
467  private:
468   Label label_;
469   LLabel* replacement_;
470 };
471
472
473 class LParameter V8_FINAL : public LTemplateInstruction<1, 0, 0> {
474  public:
475   virtual bool HasInterestingComment(LCodeGen* gen) const V8_OVERRIDE {
476     return false;
477   }
478   DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
479 };
480
481
482 class LCallStub V8_FINAL : public LTemplateInstruction<1, 1, 0> {
483  public:
484   explicit LCallStub(LOperand* context) {
485     inputs_[0] = context;
486   }
487
488   LOperand* context() { return inputs_[0]; }
489
490   DECLARE_CONCRETE_INSTRUCTION(CallStub, "call-stub")
491   DECLARE_HYDROGEN_ACCESSOR(CallStub)
492 };
493
494
495 class LUnknownOSRValue V8_FINAL : public LTemplateInstruction<1, 0, 0> {
496  public:
497   virtual bool HasInterestingComment(LCodeGen* gen) const V8_OVERRIDE {
498     return false;
499   }
500   DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown-osr-value")
501 };
502
503
504 template<int I, int T>
505 class LControlInstruction : public LTemplateInstruction<0, I, T> {
506  public:
507   LControlInstruction() : false_label_(NULL), true_label_(NULL) { }
508
509   virtual bool IsControl() const V8_FINAL V8_OVERRIDE { return true; }
510
511   int SuccessorCount() { return hydrogen()->SuccessorCount(); }
512   HBasicBlock* SuccessorAt(int i) { return hydrogen()->SuccessorAt(i); }
513
514   int TrueDestination(LChunk* chunk) {
515     return chunk->LookupDestination(true_block_id());
516   }
517   int FalseDestination(LChunk* chunk) {
518     return chunk->LookupDestination(false_block_id());
519   }
520
521   Label* TrueLabel(LChunk* chunk) {
522     if (true_label_ == NULL) {
523       true_label_ = chunk->GetAssemblyLabel(TrueDestination(chunk));
524     }
525     return true_label_;
526   }
527   Label* FalseLabel(LChunk* chunk) {
528     if (false_label_ == NULL) {
529       false_label_ = chunk->GetAssemblyLabel(FalseDestination(chunk));
530     }
531     return false_label_;
532   }
533
534  protected:
535   int true_block_id() { return SuccessorAt(0)->block_id(); }
536   int false_block_id() { return SuccessorAt(1)->block_id(); }
537
538  private:
539   HControlInstruction* hydrogen() {
540     return HControlInstruction::cast(this->hydrogen_value());
541   }
542
543   Label* false_label_;
544   Label* true_label_;
545 };
546
547
548 class LWrapReceiver V8_FINAL : public LTemplateInstruction<1, 2, 0> {
549  public:
550   LWrapReceiver(LOperand* receiver, LOperand* function) {
551     inputs_[0] = receiver;
552     inputs_[1] = function;
553   }
554
555   LOperand* receiver() { return inputs_[0]; }
556   LOperand* function() { return inputs_[1]; }
557
558   DECLARE_CONCRETE_INSTRUCTION(WrapReceiver, "wrap-receiver")
559 };
560
561
562 class LApplyArguments V8_FINAL : public LTemplateInstruction<1, 4, 0> {
563  public:
564   LApplyArguments(LOperand* function,
565                   LOperand* receiver,
566                   LOperand* length,
567                   LOperand* elements) {
568     inputs_[0] = function;
569     inputs_[1] = receiver;
570     inputs_[2] = length;
571     inputs_[3] = elements;
572   }
573
574   LOperand* function() { return inputs_[0]; }
575   LOperand* receiver() { return inputs_[1]; }
576   LOperand* length() { return inputs_[2]; }
577   LOperand* elements() { return inputs_[3]; }
578
579   DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply-arguments")
580 };
581
582
583 class LAccessArgumentsAt V8_FINAL : public LTemplateInstruction<1, 3, 0> {
584  public:
585   LAccessArgumentsAt(LOperand* arguments, LOperand* length, LOperand* index) {
586     inputs_[0] = arguments;
587     inputs_[1] = length;
588     inputs_[2] = index;
589   }
590
591   LOperand* arguments() { return inputs_[0]; }
592   LOperand* length() { return inputs_[1]; }
593   LOperand* index() { return inputs_[2]; }
594
595   DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access-arguments-at")
596
597   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
598 };
599
600
601 class LArgumentsLength V8_FINAL : public LTemplateInstruction<1, 1, 0> {
602  public:
603   explicit LArgumentsLength(LOperand* elements) {
604     inputs_[0] = elements;
605   }
606
607   LOperand* elements() { return inputs_[0]; }
608
609   DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments-length")
610 };
611
612
613 class LArgumentsElements V8_FINAL : public LTemplateInstruction<1, 0, 0> {
614  public:
615   DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments-elements")
616   DECLARE_HYDROGEN_ACCESSOR(ArgumentsElements)
617 };
618
619
620 class LModI V8_FINAL : public LTemplateInstruction<1, 2, 1> {
621  public:
622   LModI(LOperand* left, LOperand* right, LOperand* temp) {
623     inputs_[0] = left;
624     inputs_[1] = right;
625     temps_[0] = temp;
626   }
627
628   LOperand* left() { return inputs_[0]; }
629   LOperand* right() { return inputs_[1]; }
630   LOperand* temp() { return temps_[0]; }
631
632   DECLARE_CONCRETE_INSTRUCTION(ModI, "mod-i")
633   DECLARE_HYDROGEN_ACCESSOR(Mod)
634 };
635
636
637 class LDivI V8_FINAL : public LTemplateInstruction<1, 2, 1> {
638  public:
639   LDivI(LOperand* left, LOperand* right, LOperand* temp) {
640     inputs_[0] = left;
641     inputs_[1] = right;
642     temps_[0] = temp;
643   }
644
645   LOperand* left() { return inputs_[0]; }
646   LOperand* right() { return inputs_[1]; }
647   LOperand* temp() { return temps_[0]; }
648
649   bool is_flooring() { return hydrogen_value()->IsMathFloorOfDiv(); }
650
651   DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
652   DECLARE_HYDROGEN_ACCESSOR(Div)
653 };
654
655
656 class LMathFloorOfDiv V8_FINAL : public LTemplateInstruction<1, 2, 1> {
657  public:
658   LMathFloorOfDiv(LOperand* left,
659                   LOperand* right,
660                   LOperand* temp = NULL) {
661     inputs_[0] = left;
662     inputs_[1] = right;
663     temps_[0] = temp;
664   }
665
666   LOperand* left() { return inputs_[0]; }
667   LOperand* right() { return inputs_[1]; }
668   LOperand* temp() { return temps_[0]; }
669
670   DECLARE_CONCRETE_INSTRUCTION(MathFloorOfDiv, "math-floor-of-div")
671   DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
672 };
673
674
675 class LMulI V8_FINAL : public LTemplateInstruction<1, 2, 0> {
676  public:
677   LMulI(LOperand* left, LOperand* right) {
678     inputs_[0] = left;
679     inputs_[1] = right;
680   }
681
682   LOperand* left() { return inputs_[0]; }
683   LOperand* right() { return inputs_[1]; }
684
685   DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-i")
686   DECLARE_HYDROGEN_ACCESSOR(Mul)
687 };
688
689
690 class LCompareNumericAndBranch V8_FINAL : public LControlInstruction<2, 0> {
691  public:
692   LCompareNumericAndBranch(LOperand* left, LOperand* right) {
693     inputs_[0] = left;
694     inputs_[1] = right;
695   }
696
697   LOperand* left() { return inputs_[0]; }
698   LOperand* right() { return inputs_[1]; }
699
700   DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch,
701                                "compare-numeric-and-branch")
702   DECLARE_HYDROGEN_ACCESSOR(CompareNumericAndBranch)
703
704   Token::Value op() const { return hydrogen()->token(); }
705   bool is_double() const {
706     return hydrogen()->representation().IsDouble();
707   }
708
709   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
710 };
711
712
713 class LMathFloor V8_FINAL : public LTemplateInstruction<1, 1, 0> {
714  public:
715   explicit LMathFloor(LOperand* value) {
716     inputs_[0] = value;
717   }
718
719   LOperand* value() { return inputs_[0]; }
720
721   DECLARE_CONCRETE_INSTRUCTION(MathFloor, "math-floor")
722   DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
723 };
724
725
726 class LMathRound V8_FINAL : public LTemplateInstruction<1, 1, 0> {
727  public:
728   explicit LMathRound(LOperand* value) {
729     inputs_[0] = value;
730   }
731
732   LOperand* value() { return inputs_[0]; }
733
734   DECLARE_CONCRETE_INSTRUCTION(MathRound, "math-round")
735   DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
736 };
737
738
739 class LMathAbs V8_FINAL : public LTemplateInstruction<1, 2, 0> {
740  public:
741   explicit LMathAbs(LOperand* context, LOperand* value) {
742     inputs_[1] = context;
743     inputs_[0] = value;
744   }
745
746   LOperand* context() { return inputs_[1]; }
747   LOperand* value() { return inputs_[0]; }
748
749   DECLARE_CONCRETE_INSTRUCTION(MathAbs, "math-abs")
750   DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
751 };
752
753
754 class LMathLog V8_FINAL : public LTemplateInstruction<1, 1, 0> {
755  public:
756   explicit LMathLog(LOperand* value) {
757     inputs_[0] = value;
758   }
759
760   LOperand* value() { return inputs_[0]; }
761
762   DECLARE_CONCRETE_INSTRUCTION(MathLog, "math-log")
763 };
764
765
766 class LMathExp V8_FINAL : public LTemplateInstruction<1, 1, 2> {
767  public:
768   LMathExp(LOperand* value, LOperand* temp1, LOperand* temp2) {
769     inputs_[0] = value;
770     temps_[0] = temp1;
771     temps_[1] = temp2;
772     ExternalReference::InitializeMathExpData();
773   }
774
775   LOperand* value() { return inputs_[0]; }
776   LOperand* temp1() { return temps_[0]; }
777   LOperand* temp2() { return temps_[1]; }
778
779   DECLARE_CONCRETE_INSTRUCTION(MathExp, "math-exp")
780 };
781
782
783 class LMathSqrt V8_FINAL : public LTemplateInstruction<1, 1, 0> {
784  public:
785   explicit LMathSqrt(LOperand* value) {
786     inputs_[0] = value;
787   }
788
789   LOperand* value() { return inputs_[0]; }
790
791   DECLARE_CONCRETE_INSTRUCTION(MathSqrt, "math-sqrt")
792 };
793
794
795 class LMathPowHalf V8_FINAL : public LTemplateInstruction<1, 1, 0> {
796  public:
797   explicit LMathPowHalf(LOperand* value) {
798     inputs_[0] = value;
799   }
800
801   LOperand* value() { return inputs_[0]; }
802
803   DECLARE_CONCRETE_INSTRUCTION(MathPowHalf, "math-pow-half")
804 };
805
806
807 class LCmpObjectEqAndBranch V8_FINAL : public LControlInstruction<2, 0> {
808  public:
809   LCmpObjectEqAndBranch(LOperand* left, LOperand* right) {
810     inputs_[0] = left;
811     inputs_[1] = right;
812   }
813
814   LOperand* left() { return inputs_[0]; }
815   LOperand* right() { return inputs_[1]; }
816
817   DECLARE_CONCRETE_INSTRUCTION(CmpObjectEqAndBranch, "cmp-object-eq-and-branch")
818 };
819
820
821 class LCmpHoleAndBranch V8_FINAL : public LControlInstruction<1, 0> {
822  public:
823   explicit LCmpHoleAndBranch(LOperand* object) {
824     inputs_[0] = object;
825   }
826
827   LOperand* object() { return inputs_[0]; }
828
829   DECLARE_CONCRETE_INSTRUCTION(CmpHoleAndBranch, "cmp-hole-and-branch")
830   DECLARE_HYDROGEN_ACCESSOR(CompareHoleAndBranch)
831 };
832
833
834 class LCompareMinusZeroAndBranch V8_FINAL : public LControlInstruction<1, 0> {
835  public:
836   explicit LCompareMinusZeroAndBranch(LOperand* value) {
837     inputs_[0] = value;
838   }
839
840   LOperand* value() { return inputs_[0]; }
841
842   DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch,
843                                "cmp-minus-zero-and-branch")
844   DECLARE_HYDROGEN_ACCESSOR(CompareMinusZeroAndBranch)
845 };
846
847
848
849 class LIsObjectAndBranch V8_FINAL : public LControlInstruction<1, 0> {
850  public:
851   explicit LIsObjectAndBranch(LOperand* value) {
852     inputs_[0] = value;
853   }
854
855   LOperand* value() { return inputs_[0]; }
856
857   DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch, "is-object-and-branch")
858   DECLARE_HYDROGEN_ACCESSOR(IsObjectAndBranch)
859
860   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
861 };
862
863
864 class LIsStringAndBranch V8_FINAL : public LControlInstruction<1, 1> {
865  public:
866   explicit LIsStringAndBranch(LOperand* value, LOperand* temp) {
867     inputs_[0] = value;
868     temps_[0] = temp;
869   }
870
871   LOperand* value() { return inputs_[0]; }
872   LOperand* temp() { return temps_[0]; }
873
874   DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch, "is-string-and-branch")
875   DECLARE_HYDROGEN_ACCESSOR(IsStringAndBranch)
876
877   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
878 };
879
880
881 class LIsSmiAndBranch V8_FINAL : public LControlInstruction<1, 0> {
882  public:
883   explicit LIsSmiAndBranch(LOperand* value) {
884     inputs_[0] = value;
885   }
886
887   LOperand* value() { return inputs_[0]; }
888
889   DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch, "is-smi-and-branch")
890   DECLARE_HYDROGEN_ACCESSOR(IsSmiAndBranch)
891
892   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
893 };
894
895
896 class LIsUndetectableAndBranch V8_FINAL : public LControlInstruction<1, 1> {
897  public:
898   explicit LIsUndetectableAndBranch(LOperand* value, LOperand* temp) {
899     inputs_[0] = value;
900     temps_[0] = temp;
901   }
902
903   LOperand* value() { return inputs_[0]; }
904   LOperand* temp() { return temps_[0]; }
905
906   DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch,
907                                "is-undetectable-and-branch")
908   DECLARE_HYDROGEN_ACCESSOR(IsUndetectableAndBranch)
909
910   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
911 };
912
913
914 class LStringCompareAndBranch V8_FINAL : public LControlInstruction<3, 0> {
915  public:
916   explicit LStringCompareAndBranch(LOperand* context,
917                                    LOperand* left,
918                                    LOperand* right) {
919     inputs_[0] = context;
920     inputs_[1] = left;
921     inputs_[2] = right;
922   }
923
924   LOperand* context() { return inputs_[0]; }
925   LOperand* left() { return inputs_[1]; }
926   LOperand* right() { return inputs_[2]; }
927
928   DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch,
929                                "string-compare-and-branch")
930   DECLARE_HYDROGEN_ACCESSOR(StringCompareAndBranch)
931
932   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
933
934   Token::Value op() const { return hydrogen()->token(); }
935 };
936
937
938 class LHasInstanceTypeAndBranch V8_FINAL : public LControlInstruction<1, 0> {
939  public:
940   explicit LHasInstanceTypeAndBranch(LOperand* value) {
941     inputs_[0] = value;
942   }
943
944   LOperand* value() { return inputs_[0]; }
945
946   DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch,
947                                "has-instance-type-and-branch")
948   DECLARE_HYDROGEN_ACCESSOR(HasInstanceTypeAndBranch)
949
950   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
951 };
952
953
954 class LGetCachedArrayIndex V8_FINAL : public LTemplateInstruction<1, 1, 0> {
955  public:
956   explicit LGetCachedArrayIndex(LOperand* value) {
957     inputs_[0] = value;
958   }
959
960   LOperand* value() { return inputs_[0]; }
961
962   DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex, "get-cached-array-index")
963   DECLARE_HYDROGEN_ACCESSOR(GetCachedArrayIndex)
964 };
965
966
967 class LHasCachedArrayIndexAndBranch V8_FINAL
968     : public LControlInstruction<1, 0> {
969  public:
970   explicit LHasCachedArrayIndexAndBranch(LOperand* value) {
971     inputs_[0] = value;
972   }
973
974   LOperand* value() { return inputs_[0]; }
975
976   DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch,
977                                "has-cached-array-index-and-branch")
978   DECLARE_HYDROGEN_ACCESSOR(HasCachedArrayIndexAndBranch)
979
980   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
981 };
982
983
984 class LClassOfTestAndBranch V8_FINAL : public LControlInstruction<1, 2> {
985  public:
986   LClassOfTestAndBranch(LOperand* value, LOperand* temp, LOperand* temp2) {
987     inputs_[0] = value;
988     temps_[0] = temp;
989     temps_[1] = temp2;
990   }
991
992   LOperand* value() { return inputs_[0]; }
993   LOperand* temp() { return temps_[0]; }
994   LOperand* temp2() { return temps_[1]; }
995
996   DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch,
997                                "class-of-test-and-branch")
998   DECLARE_HYDROGEN_ACCESSOR(ClassOfTestAndBranch)
999
1000   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1001 };
1002
1003
1004 class LCmpT V8_FINAL : public LTemplateInstruction<1, 3, 0> {
1005  public:
1006   LCmpT(LOperand* context, LOperand* left, LOperand* right) {
1007     inputs_[0] = context;
1008     inputs_[1] = left;
1009     inputs_[2] = right;
1010   }
1011
1012   LOperand* context() { return inputs_[0]; }
1013   LOperand* left() { return inputs_[1]; }
1014   LOperand* right() { return inputs_[2]; }
1015
1016   DECLARE_CONCRETE_INSTRUCTION(CmpT, "cmp-t")
1017   DECLARE_HYDROGEN_ACCESSOR(CompareGeneric)
1018
1019   Token::Value op() const { return hydrogen()->token(); }
1020 };
1021
1022
1023 class LInstanceOf V8_FINAL : public LTemplateInstruction<1, 3, 0> {
1024  public:
1025   LInstanceOf(LOperand* context, LOperand* left, LOperand* right) {
1026     inputs_[0] = context;
1027     inputs_[1] = left;
1028     inputs_[2] = right;
1029   }
1030
1031   LOperand* context() { return inputs_[0]; }
1032   LOperand* left() { return inputs_[1]; }
1033   LOperand* right() { return inputs_[2]; }
1034
1035   DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of")
1036 };
1037
1038
1039 class LInstanceOfKnownGlobal V8_FINAL : public LTemplateInstruction<1, 2, 1> {
1040  public:
1041   LInstanceOfKnownGlobal(LOperand* context, LOperand* value, LOperand* temp) {
1042     inputs_[0] = context;
1043     inputs_[1] = value;
1044     temps_[0] = temp;
1045   }
1046
1047   LOperand* context() { return inputs_[0]; }
1048   LOperand* value() { return inputs_[1]; }
1049   LOperand* temp() { return temps_[0]; }
1050
1051   DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal,
1052                                "instance-of-known-global")
1053   DECLARE_HYDROGEN_ACCESSOR(InstanceOfKnownGlobal)
1054
1055   Handle<JSFunction> function() const { return hydrogen()->function(); }
1056   LEnvironment* GetDeferredLazyDeoptimizationEnvironment() {
1057     return lazy_deopt_env_;
1058   }
1059   virtual void SetDeferredLazyDeoptimizationEnvironment(
1060       LEnvironment* env) V8_OVERRIDE {
1061     lazy_deopt_env_ = env;
1062   }
1063
1064  private:
1065   LEnvironment* lazy_deopt_env_;
1066 };
1067
1068
1069 class LBoundsCheck V8_FINAL : public LTemplateInstruction<0, 2, 0> {
1070  public:
1071   LBoundsCheck(LOperand* index, LOperand* length) {
1072     inputs_[0] = index;
1073     inputs_[1] = length;
1074   }
1075
1076   LOperand* index() { return inputs_[0]; }
1077   LOperand* length() { return inputs_[1]; }
1078
1079   DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check")
1080   DECLARE_HYDROGEN_ACCESSOR(BoundsCheck)
1081 };
1082
1083
1084 class LBitI V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1085  public:
1086   LBitI(LOperand* left, LOperand* right) {
1087     inputs_[0] = left;
1088     inputs_[1] = right;
1089   }
1090
1091   LOperand* left() { return inputs_[0]; }
1092   LOperand* right() { return inputs_[1]; }
1093
1094   Token::Value op() const { return hydrogen()->op(); }
1095
1096   DECLARE_CONCRETE_INSTRUCTION(BitI, "bit-i")
1097   DECLARE_HYDROGEN_ACCESSOR(Bitwise)
1098 };
1099
1100
1101 class LShiftI V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1102  public:
1103   LShiftI(Token::Value op, LOperand* left, LOperand* right, bool can_deopt)
1104       : op_(op), can_deopt_(can_deopt) {
1105     inputs_[0] = left;
1106     inputs_[1] = right;
1107   }
1108
1109   Token::Value op() const { return op_; }
1110   LOperand* left() { return inputs_[0]; }
1111   LOperand* right() { return inputs_[1]; }
1112   bool can_deopt() const { return can_deopt_; }
1113
1114   DECLARE_CONCRETE_INSTRUCTION(ShiftI, "shift-i")
1115
1116  private:
1117   Token::Value op_;
1118   bool can_deopt_;
1119 };
1120
1121
1122 class LSubI V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1123  public:
1124   LSubI(LOperand* left, LOperand* right) {
1125     inputs_[0] = left;
1126     inputs_[1] = right;
1127   }
1128
1129   LOperand* left() { return inputs_[0]; }
1130   LOperand* right() { return inputs_[1]; }
1131
1132   DECLARE_CONCRETE_INSTRUCTION(SubI, "sub-i")
1133   DECLARE_HYDROGEN_ACCESSOR(Sub)
1134 };
1135
1136
1137 class LConstantI V8_FINAL : public LTemplateInstruction<1, 0, 0> {
1138  public:
1139   DECLARE_CONCRETE_INSTRUCTION(ConstantI, "constant-i")
1140   DECLARE_HYDROGEN_ACCESSOR(Constant)
1141
1142   int32_t value() const { return hydrogen()->Integer32Value(); }
1143 };
1144
1145
1146 class LConstantS V8_FINAL : public LTemplateInstruction<1, 0, 0> {
1147  public:
1148   DECLARE_CONCRETE_INSTRUCTION(ConstantS, "constant-s")
1149   DECLARE_HYDROGEN_ACCESSOR(Constant)
1150
1151   Smi* value() const { return Smi::FromInt(hydrogen()->Integer32Value()); }
1152 };
1153
1154
1155 class LConstantD V8_FINAL : public LTemplateInstruction<1, 0, 1> {
1156  public:
1157   explicit LConstantD(LOperand* temp) {
1158     temps_[0] = temp;
1159   }
1160
1161   LOperand* temp() { return temps_[0]; }
1162
1163   DECLARE_CONCRETE_INSTRUCTION(ConstantD, "constant-d")
1164   DECLARE_HYDROGEN_ACCESSOR(Constant)
1165
1166   double value() const { return hydrogen()->DoubleValue(); }
1167 };
1168
1169
1170 class LConstantE V8_FINAL : public LTemplateInstruction<1, 0, 0> {
1171  public:
1172   DECLARE_CONCRETE_INSTRUCTION(ConstantE, "constant-e")
1173   DECLARE_HYDROGEN_ACCESSOR(Constant)
1174
1175   ExternalReference value() const {
1176     return hydrogen()->ExternalReferenceValue();
1177   }
1178 };
1179
1180
1181 class LConstantT V8_FINAL : public LTemplateInstruction<1, 0, 0> {
1182  public:
1183   DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t")
1184   DECLARE_HYDROGEN_ACCESSOR(Constant)
1185
1186   Handle<Object> value(Isolate* isolate) const {
1187     return hydrogen()->handle(isolate);
1188   }
1189 };
1190
1191
1192 class LBranch V8_FINAL : public LControlInstruction<1, 0> {
1193  public:
1194   explicit LBranch(LOperand* value) {
1195     inputs_[0] = value;
1196   }
1197
1198   LOperand* value() { return inputs_[0]; }
1199
1200   DECLARE_CONCRETE_INSTRUCTION(Branch, "branch")
1201   DECLARE_HYDROGEN_ACCESSOR(Branch)
1202
1203   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1204 };
1205
1206
1207 class LDebugBreak V8_FINAL : public LTemplateInstruction<0, 0, 0> {
1208  public:
1209   DECLARE_CONCRETE_INSTRUCTION(DebugBreak, "break")
1210 };
1211
1212
1213 class LCmpMapAndBranch V8_FINAL : public LControlInstruction<1, 0> {
1214  public:
1215   explicit LCmpMapAndBranch(LOperand* value) {
1216     inputs_[0] = value;
1217   }
1218
1219   LOperand* value() { return inputs_[0]; }
1220
1221   DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch")
1222   DECLARE_HYDROGEN_ACCESSOR(CompareMap)
1223
1224   Handle<Map> map() const { return hydrogen()->map().handle(); }
1225 };
1226
1227
1228 class LMapEnumLength V8_FINAL : public LTemplateInstruction<1, 1, 0> {
1229  public:
1230   explicit LMapEnumLength(LOperand* value) {
1231     inputs_[0] = value;
1232   }
1233
1234   LOperand* value() { return inputs_[0]; }
1235
1236   DECLARE_CONCRETE_INSTRUCTION(MapEnumLength, "map-enum-length")
1237 };
1238
1239
1240 class LElementsKind V8_FINAL : public LTemplateInstruction<1, 1, 0> {
1241  public:
1242   explicit LElementsKind(LOperand* value) {
1243     inputs_[0] = value;
1244   }
1245
1246   LOperand* value() { return inputs_[0]; }
1247
1248   DECLARE_CONCRETE_INSTRUCTION(ElementsKind, "elements-kind")
1249   DECLARE_HYDROGEN_ACCESSOR(ElementsKind)
1250 };
1251
1252
1253 class LValueOf V8_FINAL : public LTemplateInstruction<1, 1, 0> {
1254  public:
1255   explicit LValueOf(LOperand* value) {
1256     inputs_[0] = value;
1257   }
1258
1259   LOperand* value() { return inputs_[0]; }
1260
1261   DECLARE_CONCRETE_INSTRUCTION(ValueOf, "value-of")
1262   DECLARE_HYDROGEN_ACCESSOR(ValueOf)
1263 };
1264
1265
1266 class LDateField V8_FINAL : public LTemplateInstruction<1, 1, 0> {
1267  public:
1268   LDateField(LOperand* date, Smi* index) : index_(index) {
1269     inputs_[0] = date;
1270   }
1271
1272   LOperand* date() { return inputs_[0]; }
1273   Smi* index() const { return index_; }
1274
1275   DECLARE_CONCRETE_INSTRUCTION(DateField, "date-field")
1276   DECLARE_HYDROGEN_ACCESSOR(DateField)
1277
1278  private:
1279   Smi* index_;
1280 };
1281
1282
1283 class LSeqStringGetChar V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1284  public:
1285   LSeqStringGetChar(LOperand* string, LOperand* index) {
1286     inputs_[0] = string;
1287     inputs_[1] = index;
1288   }
1289
1290   LOperand* string() const { return inputs_[0]; }
1291   LOperand* index() const { return inputs_[1]; }
1292
1293   DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar, "seq-string-get-char")
1294   DECLARE_HYDROGEN_ACCESSOR(SeqStringGetChar)
1295 };
1296
1297
1298 class LSeqStringSetChar V8_FINAL : public LTemplateInstruction<1, 4, 0> {
1299  public:
1300   LSeqStringSetChar(LOperand* context,
1301                     LOperand* string,
1302                     LOperand* index,
1303                     LOperand* value) {
1304     inputs_[0] = context;
1305     inputs_[1] = string;
1306     inputs_[2] = index;
1307     inputs_[3] = value;
1308   }
1309
1310   LOperand* string() { return inputs_[1]; }
1311   LOperand* index() { return inputs_[2]; }
1312   LOperand* value() { return inputs_[3]; }
1313
1314   DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar, "seq-string-set-char")
1315   DECLARE_HYDROGEN_ACCESSOR(SeqStringSetChar)
1316 };
1317
1318
1319 class LThrow V8_FINAL : public LTemplateInstruction<0, 2, 0> {
1320  public:
1321   explicit LThrow(LOperand* context, LOperand* value) {
1322     inputs_[0] = context;
1323     inputs_[1] = value;
1324   }
1325
1326   LOperand* context() { return inputs_[0]; }
1327   LOperand* value() { return inputs_[1]; }
1328
1329   DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
1330 };
1331
1332
1333 class LAddI V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1334  public:
1335   LAddI(LOperand* left, LOperand* right) {
1336     inputs_[0] = left;
1337     inputs_[1] = right;
1338   }
1339
1340   LOperand* left() { return inputs_[0]; }
1341   LOperand* right() { return inputs_[1]; }
1342
1343   static bool UseLea(HAdd* add) {
1344     return !add->CheckFlag(HValue::kCanOverflow) &&
1345         add->BetterLeftOperand()->UseCount() > 1;
1346   }
1347
1348   DECLARE_CONCRETE_INSTRUCTION(AddI, "add-i")
1349   DECLARE_HYDROGEN_ACCESSOR(Add)
1350 };
1351
1352
1353 class LMathMinMax V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1354  public:
1355   LMathMinMax(LOperand* left, LOperand* right) {
1356     inputs_[0] = left;
1357     inputs_[1] = right;
1358   }
1359
1360   LOperand* left() { return inputs_[0]; }
1361   LOperand* right() { return inputs_[1]; }
1362
1363   DECLARE_CONCRETE_INSTRUCTION(MathMinMax, "math-min-max")
1364   DECLARE_HYDROGEN_ACCESSOR(MathMinMax)
1365 };
1366
1367
1368 class LPower V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1369  public:
1370   LPower(LOperand* left, LOperand* right) {
1371     inputs_[0] = left;
1372     inputs_[1] = right;
1373   }
1374
1375   LOperand* left() { return inputs_[0]; }
1376   LOperand* right() { return inputs_[1]; }
1377
1378   DECLARE_CONCRETE_INSTRUCTION(Power, "power")
1379   DECLARE_HYDROGEN_ACCESSOR(Power)
1380 };
1381
1382
1383 class LArithmeticD V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1384  public:
1385   LArithmeticD(Token::Value op, LOperand* left, LOperand* right)
1386       : op_(op) {
1387     inputs_[0] = left;
1388     inputs_[1] = right;
1389   }
1390
1391   Token::Value op() const { return op_; }
1392   LOperand* left() { return inputs_[0]; }
1393   LOperand* right() { return inputs_[1]; }
1394
1395   virtual Opcode opcode() const V8_OVERRIDE {
1396     return LInstruction::kArithmeticD;
1397   }
1398   virtual void CompileToNative(LCodeGen* generator) V8_OVERRIDE;
1399   virtual const char* Mnemonic() const V8_OVERRIDE;
1400
1401  private:
1402   Token::Value op_;
1403 };
1404
1405
1406 class LArithmeticT V8_FINAL : public LTemplateInstruction<1, 3, 0> {
1407  public:
1408   LArithmeticT(Token::Value op,
1409                LOperand* context,
1410                LOperand* left,
1411                LOperand* right)
1412       : op_(op) {
1413     inputs_[0] = context;
1414     inputs_[1] = left;
1415     inputs_[2] = right;
1416   }
1417
1418   Token::Value op() const { return op_; }
1419   LOperand* context() { return inputs_[0]; }
1420   LOperand* left() { return inputs_[1]; }
1421   LOperand* right() { return inputs_[2]; }
1422
1423   virtual Opcode opcode() const V8_OVERRIDE {
1424     return LInstruction::kArithmeticT;
1425   }
1426   virtual void CompileToNative(LCodeGen* generator) V8_OVERRIDE;
1427   virtual const char* Mnemonic() const V8_OVERRIDE;
1428
1429  private:
1430   Token::Value op_;
1431 };
1432
1433
1434 class LReturn V8_FINAL : public LTemplateInstruction<0, 3, 0> {
1435  public:
1436   explicit LReturn(LOperand* value,
1437                    LOperand* context,
1438                    LOperand* parameter_count) {
1439     inputs_[0] = value;
1440     inputs_[1] = context;
1441     inputs_[2] = parameter_count;
1442   }
1443
1444   LOperand* value() { return inputs_[0]; }
1445   LOperand* context() { return inputs_[1]; }
1446
1447   bool has_constant_parameter_count() {
1448     return parameter_count()->IsConstantOperand();
1449   }
1450   LConstantOperand* constant_parameter_count() {
1451     ASSERT(has_constant_parameter_count());
1452     return LConstantOperand::cast(parameter_count());
1453   }
1454   LOperand* parameter_count() { return inputs_[2]; }
1455
1456   DECLARE_CONCRETE_INSTRUCTION(Return, "return")
1457   DECLARE_HYDROGEN_ACCESSOR(Return)
1458 };
1459
1460
1461 class LLoadNamedField V8_FINAL : public LTemplateInstruction<1, 1, 0> {
1462  public:
1463   explicit LLoadNamedField(LOperand* object) {
1464     inputs_[0] = object;
1465   }
1466
1467   LOperand* object() { return inputs_[0]; }
1468
1469   DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field")
1470   DECLARE_HYDROGEN_ACCESSOR(LoadNamedField)
1471 };
1472
1473
1474 class LLoadNamedGeneric V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1475  public:
1476   explicit LLoadNamedGeneric(LOperand* context, LOperand* object) {
1477     inputs_[0] = context;
1478     inputs_[1] = object;
1479   }
1480
1481   DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load-named-generic")
1482   DECLARE_HYDROGEN_ACCESSOR(LoadNamedGeneric)
1483
1484   LOperand* context() { return inputs_[0]; }
1485   LOperand* object() { return inputs_[1]; }
1486   Handle<Object> name() const { return hydrogen()->name(); }
1487 };
1488
1489
1490 class LLoadFunctionPrototype V8_FINAL : public LTemplateInstruction<1, 1, 0> {
1491  public:
1492   explicit LLoadFunctionPrototype(LOperand* function) {
1493     inputs_[0] = function;
1494   }
1495
1496   DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype")
1497   DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype)
1498
1499   LOperand* function() { return inputs_[0]; }
1500 };
1501
1502
1503 class LLoadRoot V8_FINAL : public LTemplateInstruction<1, 0, 0> {
1504  public:
1505   DECLARE_CONCRETE_INSTRUCTION(LoadRoot, "load-root")
1506   DECLARE_HYDROGEN_ACCESSOR(LoadRoot)
1507
1508   Heap::RootListIndex index() const { return hydrogen()->index(); }
1509 };
1510
1511
1512 class LLoadExternalArrayPointer V8_FINAL
1513     : public LTemplateInstruction<1, 1, 0> {
1514  public:
1515   explicit LLoadExternalArrayPointer(LOperand* object) {
1516     inputs_[0] = object;
1517   }
1518
1519   LOperand* object() { return inputs_[0]; }
1520
1521   DECLARE_CONCRETE_INSTRUCTION(LoadExternalArrayPointer,
1522                                "load-external-array-pointer")
1523 };
1524
1525
1526 class LLoadKeyed V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1527  public:
1528   LLoadKeyed(LOperand* elements, LOperand* key) {
1529     inputs_[0] = elements;
1530     inputs_[1] = key;
1531   }
1532
1533   DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
1534   DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
1535
1536   bool is_external() const {
1537     return hydrogen()->is_external();
1538   }
1539   LOperand* elements() { return inputs_[0]; }
1540   LOperand* key() { return inputs_[1]; }
1541   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1542   uint32_t additional_index() const { return hydrogen()->index_offset(); }
1543   ElementsKind elements_kind() const {
1544     return hydrogen()->elements_kind();
1545   }
1546 };
1547
1548
1549 class LLoadKeyedGeneric V8_FINAL : public LTemplateInstruction<1, 3, 0> {
1550  public:
1551   LLoadKeyedGeneric(LOperand* context, LOperand* obj, LOperand* key) {
1552     inputs_[0] = context;
1553     inputs_[1] = obj;
1554     inputs_[2] = key;
1555   }
1556
1557   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load-keyed-generic")
1558
1559   LOperand* context() { return inputs_[0]; }
1560   LOperand* object() { return inputs_[1]; }
1561   LOperand* key() { return inputs_[2]; }
1562 };
1563
1564
1565 class LLoadGlobalCell V8_FINAL : public LTemplateInstruction<1, 0, 0> {
1566  public:
1567   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell, "load-global-cell")
1568   DECLARE_HYDROGEN_ACCESSOR(LoadGlobalCell)
1569 };
1570
1571
1572 class LLoadGlobalGeneric V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1573  public:
1574   explicit LLoadGlobalGeneric(LOperand* context, LOperand* global_object) {
1575     inputs_[0] = context;
1576     inputs_[1] = global_object;
1577   }
1578
1579   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
1580   DECLARE_HYDROGEN_ACCESSOR(LoadGlobalGeneric)
1581
1582   LOperand* context() { return inputs_[0]; }
1583   LOperand* global_object() { return inputs_[1]; }
1584   Handle<Object> name() const { return hydrogen()->name(); }
1585   bool for_typeof() const { return hydrogen()->for_typeof(); }
1586 };
1587
1588
1589 class LStoreGlobalCell V8_FINAL : public LTemplateInstruction<0, 1, 1> {
1590  public:
1591   explicit LStoreGlobalCell(LOperand* value, LOperand* temp) {
1592     inputs_[0] = value;
1593     temps_[0] = temp;
1594   }
1595
1596   LOperand* value() { return inputs_[0]; }
1597   LOperand* temp() { return temps_[0]; }
1598
1599   DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell, "store-global-cell")
1600   DECLARE_HYDROGEN_ACCESSOR(StoreGlobalCell)
1601 };
1602
1603
1604 class LStoreGlobalGeneric V8_FINAL : public LTemplateInstruction<0, 3, 0> {
1605  public:
1606   explicit LStoreGlobalGeneric(LOperand* context,
1607                                LOperand* global_object,
1608                                LOperand* value) {
1609     inputs_[0] = context;
1610     inputs_[1] = global_object;
1611     inputs_[2] = value;
1612   }
1613
1614   LOperand* context() { return inputs_[0]; }
1615   LOperand* global_object() { return inputs_[1]; }
1616   LOperand* value() { return inputs_[2]; }
1617
1618   DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric, "store-global-generic")
1619   DECLARE_HYDROGEN_ACCESSOR(StoreGlobalGeneric)
1620
1621   Handle<Object> name() const { return hydrogen()->name(); }
1622   StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
1623 };
1624
1625
1626 class LLoadContextSlot V8_FINAL : public LTemplateInstruction<1, 1, 0> {
1627  public:
1628   explicit LLoadContextSlot(LOperand* context) {
1629     inputs_[0] = context;
1630   }
1631
1632   LOperand* context() { return inputs_[0]; }
1633
1634   DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load-context-slot")
1635   DECLARE_HYDROGEN_ACCESSOR(LoadContextSlot)
1636
1637   int slot_index() { return hydrogen()->slot_index(); }
1638
1639   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1640 };
1641
1642
1643 class LStoreContextSlot V8_FINAL : public LTemplateInstruction<0, 2, 1> {
1644  public:
1645   LStoreContextSlot(LOperand* context, LOperand* value, LOperand* temp) {
1646     inputs_[0] = context;
1647     inputs_[1] = value;
1648     temps_[0] = temp;
1649   }
1650
1651   LOperand* context() { return inputs_[0]; }
1652   LOperand* value() { return inputs_[1]; }
1653   LOperand* temp() { return temps_[0]; }
1654
1655   DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store-context-slot")
1656   DECLARE_HYDROGEN_ACCESSOR(StoreContextSlot)
1657
1658   int slot_index() { return hydrogen()->slot_index(); }
1659
1660   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1661 };
1662
1663
1664 class LPushArgument V8_FINAL : public LTemplateInstruction<0, 1, 0> {
1665  public:
1666   explicit LPushArgument(LOperand* value) {
1667     inputs_[0] = value;
1668   }
1669
1670   LOperand* value() { return inputs_[0]; }
1671
1672   DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push-argument")
1673 };
1674
1675
1676 class LDrop V8_FINAL : public LTemplateInstruction<0, 0, 0> {
1677  public:
1678   explicit LDrop(int count) : count_(count) { }
1679
1680   int count() const { return count_; }
1681
1682   DECLARE_CONCRETE_INSTRUCTION(Drop, "drop")
1683
1684  private:
1685   int count_;
1686 };
1687
1688
1689 class LStoreCodeEntry V8_FINAL: public LTemplateInstruction<0, 1, 1> {
1690  public:
1691   LStoreCodeEntry(LOperand* function, LOperand* code_object) {
1692     inputs_[0] = function;
1693     temps_[0] = code_object;
1694   }
1695
1696   LOperand* function() { return inputs_[0]; }
1697   LOperand* code_object() { return temps_[0]; }
1698
1699   virtual void PrintDataTo(StringStream* stream);
1700
1701   DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry, "store-code-entry")
1702   DECLARE_HYDROGEN_ACCESSOR(StoreCodeEntry)
1703 };
1704
1705
1706 class LInnerAllocatedObject V8_FINAL: public LTemplateInstruction<1, 2, 0> {
1707  public:
1708   LInnerAllocatedObject(LOperand* base_object, LOperand* offset) {
1709     inputs_[0] = base_object;
1710     inputs_[1] = offset;
1711   }
1712
1713   LOperand* base_object() const { return inputs_[0]; }
1714   LOperand* offset() const { return inputs_[1]; }
1715
1716   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1717
1718   DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject, "inner-allocated-object")
1719 };
1720
1721
1722 class LThisFunction V8_FINAL : public LTemplateInstruction<1, 0, 0> {
1723  public:
1724   DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function")
1725   DECLARE_HYDROGEN_ACCESSOR(ThisFunction)
1726 };
1727
1728
1729 class LContext V8_FINAL : public LTemplateInstruction<1, 0, 0> {
1730  public:
1731   DECLARE_CONCRETE_INSTRUCTION(Context, "context")
1732   DECLARE_HYDROGEN_ACCESSOR(Context)
1733 };
1734
1735
1736 class LOuterContext V8_FINAL : public LTemplateInstruction<1, 1, 0> {
1737  public:
1738   explicit LOuterContext(LOperand* context) {
1739     inputs_[0] = context;
1740   }
1741
1742   LOperand* context() { return inputs_[0]; }
1743
1744   DECLARE_CONCRETE_INSTRUCTION(OuterContext, "outer-context")
1745 };
1746
1747
1748 class LDeclareGlobals V8_FINAL : public LTemplateInstruction<0, 1, 0> {
1749  public:
1750   explicit LDeclareGlobals(LOperand* context) {
1751     inputs_[0] = context;
1752   }
1753
1754   LOperand* context() { return inputs_[0]; }
1755
1756   DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals, "declare-globals")
1757   DECLARE_HYDROGEN_ACCESSOR(DeclareGlobals)
1758 };
1759
1760
1761 class LGlobalObject V8_FINAL : public LTemplateInstruction<1, 1, 0> {
1762  public:
1763   explicit LGlobalObject(LOperand* context) {
1764     inputs_[0] = context;
1765   }
1766
1767   LOperand* context() { return inputs_[0]; }
1768
1769   DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object")
1770 };
1771
1772
1773 class LGlobalReceiver V8_FINAL : public LTemplateInstruction<1, 1, 0> {
1774  public:
1775   explicit LGlobalReceiver(LOperand* global_object) {
1776     inputs_[0] = global_object;
1777   }
1778
1779   LOperand* global() { return inputs_[0]; }
1780
1781   DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global-receiver")
1782 };
1783
1784
1785 class LCallConstantFunction V8_FINAL : public LTemplateInstruction<1, 0, 0> {
1786  public:
1787   DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction, "call-constant-function")
1788   DECLARE_HYDROGEN_ACCESSOR(CallConstantFunction)
1789
1790   virtual void PrintDataTo(StringStream* stream);
1791
1792   Handle<JSFunction> function() { return hydrogen()->function(); }
1793   int arity() const { return hydrogen()->argument_count() - 1; }
1794 };
1795
1796
1797 class LInvokeFunction V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1798  public:
1799   LInvokeFunction(LOperand* context, LOperand* function) {
1800     inputs_[0] = context;
1801     inputs_[1] = function;
1802   }
1803
1804   LOperand* context() { return inputs_[0]; }
1805   LOperand* function() { return inputs_[1]; }
1806
1807   DECLARE_CONCRETE_INSTRUCTION(InvokeFunction, "invoke-function")
1808   DECLARE_HYDROGEN_ACCESSOR(InvokeFunction)
1809
1810   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1811
1812   int arity() const { return hydrogen()->argument_count() - 1; }
1813 };
1814
1815
1816 class LCallKeyed V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1817  public:
1818   LCallKeyed(LOperand* context, LOperand* key) {
1819     inputs_[0] = context;
1820     inputs_[1] = key;
1821   }
1822
1823   DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call-keyed")
1824   DECLARE_HYDROGEN_ACCESSOR(CallKeyed)
1825
1826   LOperand* context() { return inputs_[0]; }
1827   LOperand* key() { return inputs_[1]; }
1828
1829   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1830
1831   int arity() const { return hydrogen()->argument_count() - 1; }
1832 };
1833
1834
1835 class LCallNamed V8_FINAL : public LTemplateInstruction<1, 1, 0> {
1836  public:
1837   explicit LCallNamed(LOperand* context) {
1838     inputs_[0] = context;
1839   }
1840
1841   LOperand* context() { return inputs_[0]; }
1842
1843   DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call-named")
1844   DECLARE_HYDROGEN_ACCESSOR(CallNamed)
1845
1846   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1847
1848   Handle<String> name() const { return hydrogen()->name(); }
1849   int arity() const { return hydrogen()->argument_count() - 1; }
1850 };
1851
1852
1853 class LCallFunction V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1854  public:
1855   LCallFunction(LOperand* context, LOperand* function) {
1856     inputs_[0] = context;
1857     inputs_[1] = function;
1858   }
1859
1860   DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call-function")
1861   DECLARE_HYDROGEN_ACCESSOR(CallFunction)
1862
1863   LOperand* context() { return inputs_[0]; }
1864   LOperand* function() { return inputs_[1]; }
1865   int arity() const { return hydrogen()->argument_count() - 1; }
1866 };
1867
1868
1869 class LCallGlobal V8_FINAL : public LTemplateInstruction<1, 1, 0> {
1870  public:
1871   explicit LCallGlobal(LOperand* context) {
1872     inputs_[0] = context;
1873   }
1874
1875   LOperand* context() { return inputs_[0]; }
1876
1877   DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call-global")
1878   DECLARE_HYDROGEN_ACCESSOR(CallGlobal)
1879
1880   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1881
1882   Handle<String> name() const {return hydrogen()->name(); }
1883   int arity() const { return hydrogen()->argument_count() - 1; }
1884 };
1885
1886
1887 class LCallKnownGlobal V8_FINAL : public LTemplateInstruction<1, 0, 0> {
1888  public:
1889   DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call-known-global")
1890   DECLARE_HYDROGEN_ACCESSOR(CallKnownGlobal)
1891
1892   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1893
1894   int arity() const { return hydrogen()->argument_count() - 1;  }
1895 };
1896
1897
1898 class LCallNew V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1899  public:
1900   LCallNew(LOperand* context, LOperand* constructor) {
1901     inputs_[0] = context;
1902     inputs_[1] = constructor;
1903   }
1904
1905   LOperand* context() { return inputs_[0]; }
1906   LOperand* constructor() { return inputs_[1]; }
1907
1908   DECLARE_CONCRETE_INSTRUCTION(CallNew, "call-new")
1909   DECLARE_HYDROGEN_ACCESSOR(CallNew)
1910
1911   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1912
1913   int arity() const { return hydrogen()->argument_count() - 1; }
1914 };
1915
1916
1917 class LCallNewArray V8_FINAL : public LTemplateInstruction<1, 2, 0> {
1918  public:
1919   LCallNewArray(LOperand* context, LOperand* constructor) {
1920     inputs_[0] = context;
1921     inputs_[1] = constructor;
1922   }
1923
1924   LOperand* context() { return inputs_[0]; }
1925   LOperand* constructor() { return inputs_[1]; }
1926
1927   DECLARE_CONCRETE_INSTRUCTION(CallNewArray, "call-new-array")
1928   DECLARE_HYDROGEN_ACCESSOR(CallNewArray)
1929
1930   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
1931
1932   int arity() const { return hydrogen()->argument_count() - 1; }
1933 };
1934
1935
1936 class LCallRuntime V8_FINAL : public LTemplateInstruction<1, 1, 0> {
1937  public:
1938   explicit LCallRuntime(LOperand* context) {
1939     inputs_[0] = context;
1940   }
1941
1942   LOperand* context() { return inputs_[0]; }
1943
1944   DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime")
1945   DECLARE_HYDROGEN_ACCESSOR(CallRuntime)
1946
1947   virtual bool ClobbersDoubleRegisters() const V8_OVERRIDE {
1948     return save_doubles() == kDontSaveFPRegs;
1949   }
1950
1951   const Runtime::Function* function() const { return hydrogen()->function(); }
1952   int arity() const { return hydrogen()->argument_count(); }
1953   SaveFPRegsMode save_doubles() const { return hydrogen()->save_doubles(); }
1954 };
1955
1956
1957 class LInteger32ToDouble V8_FINAL : public LTemplateInstruction<1, 1, 0> {
1958  public:
1959   explicit LInteger32ToDouble(LOperand* value) {
1960     inputs_[0] = value;
1961   }
1962
1963   LOperand* value() { return inputs_[0]; }
1964
1965   DECLARE_CONCRETE_INSTRUCTION(Integer32ToDouble, "int32-to-double")
1966 };
1967
1968
1969 class LInteger32ToSmi V8_FINAL : public LTemplateInstruction<1, 1, 0> {
1970  public:
1971   explicit LInteger32ToSmi(LOperand* value) {
1972     inputs_[0] = value;
1973   }
1974
1975   LOperand* value() { return inputs_[0]; }
1976
1977   DECLARE_CONCRETE_INSTRUCTION(Integer32ToSmi, "int32-to-smi")
1978   DECLARE_HYDROGEN_ACCESSOR(Change)
1979 };
1980
1981
1982 class LUint32ToDouble V8_FINAL : public LTemplateInstruction<1, 1, 1> {
1983  public:
1984   explicit LUint32ToDouble(LOperand* value, LOperand* temp) {
1985     inputs_[0] = value;
1986     temps_[0] = temp;
1987   }
1988
1989   LOperand* value() { return inputs_[0]; }
1990   LOperand* temp() { return temps_[0]; }
1991
1992   DECLARE_CONCRETE_INSTRUCTION(Uint32ToDouble, "uint32-to-double")
1993 };
1994
1995
1996 class LUint32ToSmi V8_FINAL : public LTemplateInstruction<1, 1, 0> {
1997  public:
1998   explicit LUint32ToSmi(LOperand* value) {
1999     inputs_[0] = value;
2000   }
2001
2002   LOperand* value() { return inputs_[0]; }
2003
2004   DECLARE_CONCRETE_INSTRUCTION(Uint32ToSmi, "uint32-to-smi")
2005   DECLARE_HYDROGEN_ACCESSOR(Change)
2006 };
2007
2008
2009 class LNumberTagI V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2010  public:
2011   explicit LNumberTagI(LOperand* value) {
2012     inputs_[0] = value;
2013   }
2014
2015   LOperand* value() { return inputs_[0]; }
2016
2017   DECLARE_CONCRETE_INSTRUCTION(NumberTagI, "number-tag-i")
2018 };
2019
2020
2021 class LNumberTagU V8_FINAL : public LTemplateInstruction<1, 1, 1> {
2022  public:
2023   explicit LNumberTagU(LOperand* value, LOperand* temp) {
2024     inputs_[0] = value;
2025     temps_[0] = temp;
2026   }
2027
2028   LOperand* value() { return inputs_[0]; }
2029   LOperand* temp() { return temps_[0]; }
2030
2031   DECLARE_CONCRETE_INSTRUCTION(NumberTagU, "number-tag-u")
2032 };
2033
2034
2035 class LNumberTagD V8_FINAL : public LTemplateInstruction<1, 1, 1> {
2036  public:
2037   explicit LNumberTagD(LOperand* value, LOperand* temp) {
2038     inputs_[0] = value;
2039     temps_[0] = temp;
2040   }
2041
2042   LOperand* value() { return inputs_[0]; }
2043   LOperand* temp() { return temps_[0]; }
2044
2045   DECLARE_CONCRETE_INSTRUCTION(NumberTagD, "number-tag-d")
2046   DECLARE_HYDROGEN_ACCESSOR(Change)
2047 };
2048
2049
2050 // Sometimes truncating conversion from a tagged value to an int32.
2051 class LDoubleToI V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2052  public:
2053   explicit LDoubleToI(LOperand* value) {
2054     inputs_[0] = value;
2055   }
2056
2057   LOperand* value() { return inputs_[0]; }
2058
2059   DECLARE_CONCRETE_INSTRUCTION(DoubleToI, "double-to-i")
2060   DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
2061
2062   bool truncating() { return hydrogen()->CanTruncateToInt32(); }
2063 };
2064
2065
2066 class LDoubleToSmi V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2067  public:
2068   explicit LDoubleToSmi(LOperand* value) {
2069     inputs_[0] = value;
2070   }
2071
2072   LOperand* value() { return inputs_[0]; }
2073
2074   DECLARE_CONCRETE_INSTRUCTION(DoubleToSmi, "double-to-smi")
2075   DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
2076 };
2077
2078
2079 // Truncating conversion from a tagged value to an int32.
2080 class LTaggedToI V8_FINAL : public LTemplateInstruction<1, 1, 1> {
2081  public:
2082   LTaggedToI(LOperand* value, LOperand* temp) {
2083     inputs_[0] = value;
2084     temps_[0] = temp;
2085   }
2086
2087   LOperand* value() { return inputs_[0]; }
2088   LOperand* temp() { return temps_[0]; }
2089
2090   DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i")
2091   DECLARE_HYDROGEN_ACCESSOR(Change)
2092
2093   bool truncating() { return hydrogen()->CanTruncateToInt32(); }
2094 };
2095
2096
2097 class LSmiTag V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2098  public:
2099   explicit LSmiTag(LOperand* value) {
2100     inputs_[0] = value;
2101   }
2102
2103   LOperand* value() { return inputs_[0]; }
2104
2105   DECLARE_CONCRETE_INSTRUCTION(SmiTag, "smi-tag")
2106 };
2107
2108
2109 class LNumberUntagD V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2110  public:
2111   explicit LNumberUntagD(LOperand* value) {
2112     inputs_[0] = value;
2113   }
2114
2115   LOperand* value() { return inputs_[0]; }
2116
2117   DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag")
2118   DECLARE_HYDROGEN_ACCESSOR(Change);
2119 };
2120
2121
2122 class LSmiUntag V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2123  public:
2124   LSmiUntag(LOperand* value, bool needs_check)
2125       : needs_check_(needs_check) {
2126     inputs_[0] = value;
2127   }
2128
2129   LOperand* value() { return inputs_[0]; }
2130   bool needs_check() const { return needs_check_; }
2131
2132   DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
2133
2134  private:
2135   bool needs_check_;
2136 };
2137
2138
2139 class LStoreNamedField V8_FINAL : public LTemplateInstruction<0, 2, 1> {
2140  public:
2141   LStoreNamedField(LOperand* object, LOperand* value, LOperand* temp) {
2142     inputs_[0] = object;
2143     inputs_[1] = value;
2144     temps_[0] = temp;
2145   }
2146
2147   LOperand* object() { return inputs_[0]; }
2148   LOperand* value() { return inputs_[1]; }
2149   LOperand* temp() { return temps_[0]; }
2150
2151   DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field")
2152   DECLARE_HYDROGEN_ACCESSOR(StoreNamedField)
2153
2154   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2155
2156   Handle<Map> transition() const { return hydrogen()->transition_map(); }
2157   Representation representation() const {
2158     return hydrogen()->field_representation();
2159   }
2160 };
2161
2162
2163 class LStoreNamedGeneric V8_FINAL : public LTemplateInstruction<0, 3, 0> {
2164  public:
2165   LStoreNamedGeneric(LOperand* context, LOperand* object, LOperand* value) {
2166     inputs_[0] = context;
2167     inputs_[1] = object;
2168     inputs_[2] = value;
2169   }
2170
2171   LOperand* context() { return inputs_[0]; }
2172   LOperand* object() { return inputs_[1]; }
2173   LOperand* value() { return inputs_[2]; }
2174
2175   DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic")
2176   DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric)
2177
2178   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2179
2180   Handle<Object> name() const { return hydrogen()->name(); }
2181   StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
2182 };
2183
2184
2185 class LStoreKeyed V8_FINAL : public LTemplateInstruction<0, 3, 0> {
2186  public:
2187   LStoreKeyed(LOperand* object, LOperand* key, LOperand* value) {
2188     inputs_[0] = object;
2189     inputs_[1] = key;
2190     inputs_[2] = value;
2191   }
2192
2193   bool is_external() const { return hydrogen()->is_external(); }
2194   LOperand* elements() { return inputs_[0]; }
2195   LOperand* key() { return inputs_[1]; }
2196   LOperand* value() { return inputs_[2]; }
2197   ElementsKind elements_kind() const { return hydrogen()->elements_kind(); }
2198
2199   DECLARE_CONCRETE_INSTRUCTION(StoreKeyed, "store-keyed")
2200   DECLARE_HYDROGEN_ACCESSOR(StoreKeyed)
2201
2202   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2203   bool NeedsCanonicalization() { return hydrogen()->NeedsCanonicalization(); }
2204   uint32_t additional_index() const { return hydrogen()->index_offset(); }
2205 };
2206
2207
2208 class LStoreKeyedGeneric V8_FINAL : public LTemplateInstruction<0, 4, 0> {
2209  public:
2210   LStoreKeyedGeneric(LOperand* context,
2211                      LOperand* object,
2212                      LOperand* key,
2213                      LOperand* value) {
2214     inputs_[0] = context;
2215     inputs_[1] = object;
2216     inputs_[2] = key;
2217     inputs_[3] = value;
2218   }
2219
2220   LOperand* context() { return inputs_[0]; }
2221   LOperand* object() { return inputs_[1]; }
2222   LOperand* key() { return inputs_[2]; }
2223   LOperand* value() { return inputs_[3]; }
2224
2225   DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic")
2226   DECLARE_HYDROGEN_ACCESSOR(StoreKeyedGeneric)
2227
2228   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2229
2230   StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
2231 };
2232
2233
2234 class LTransitionElementsKind V8_FINAL : public LTemplateInstruction<0, 2, 2> {
2235  public:
2236   LTransitionElementsKind(LOperand* object,
2237                           LOperand* context,
2238                           LOperand* new_map_temp,
2239                           LOperand* temp) {
2240     inputs_[0] = object;
2241     inputs_[1] = context;
2242     temps_[0] = new_map_temp;
2243     temps_[1] = temp;
2244   }
2245
2246   LOperand* object() { return inputs_[0]; }
2247   LOperand* context() { return inputs_[1]; }
2248   LOperand* new_map_temp() { return temps_[0]; }
2249   LOperand* temp() { return temps_[1]; }
2250
2251   DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind,
2252                                "transition-elements-kind")
2253   DECLARE_HYDROGEN_ACCESSOR(TransitionElementsKind)
2254
2255   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2256
2257   Handle<Map> original_map() { return hydrogen()->original_map().handle(); }
2258   Handle<Map> transitioned_map() {
2259     return hydrogen()->transitioned_map().handle();
2260   }
2261   ElementsKind from_kind() { return hydrogen()->from_kind(); }
2262   ElementsKind to_kind() { return hydrogen()->to_kind(); }
2263 };
2264
2265
2266 class LTrapAllocationMemento V8_FINAL : public LTemplateInstruction<0, 1, 1> {
2267  public:
2268   LTrapAllocationMemento(LOperand* object,
2269                          LOperand* temp) {
2270     inputs_[0] = object;
2271     temps_[0] = temp;
2272   }
2273
2274   LOperand* object() { return inputs_[0]; }
2275   LOperand* temp() { return temps_[0]; }
2276
2277   DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento,
2278                                "trap-allocation-memento")
2279 };
2280
2281
2282 class LStringAdd V8_FINAL : public LTemplateInstruction<1, 3, 0> {
2283  public:
2284   LStringAdd(LOperand* context, LOperand* left, LOperand* right) {
2285     inputs_[0] = context;
2286     inputs_[1] = left;
2287     inputs_[2] = right;
2288   }
2289
2290   LOperand* context() { return inputs_[0]; }
2291   LOperand* left() { return inputs_[1]; }
2292   LOperand* right() { return inputs_[2]; }
2293
2294   DECLARE_CONCRETE_INSTRUCTION(StringAdd, "string-add")
2295   DECLARE_HYDROGEN_ACCESSOR(StringAdd)
2296 };
2297
2298
2299 class LStringCharCodeAt V8_FINAL : public LTemplateInstruction<1, 3, 0> {
2300  public:
2301   LStringCharCodeAt(LOperand* context, LOperand* string, LOperand* index) {
2302     inputs_[0] = context;
2303     inputs_[1] = string;
2304     inputs_[2] = index;
2305   }
2306
2307   LOperand* context() { return inputs_[0]; }
2308   LOperand* string() { return inputs_[1]; }
2309   LOperand* index() { return inputs_[2]; }
2310
2311   DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string-char-code-at")
2312   DECLARE_HYDROGEN_ACCESSOR(StringCharCodeAt)
2313 };
2314
2315
2316 class LStringCharFromCode V8_FINAL : public LTemplateInstruction<1, 2, 0> {
2317  public:
2318   explicit LStringCharFromCode(LOperand* context, LOperand* char_code) {
2319     inputs_[0] = context;
2320     inputs_[1] = char_code;
2321   }
2322
2323   LOperand* context() { return inputs_[0]; }
2324   LOperand* char_code() { return inputs_[1]; }
2325
2326   DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode, "string-char-from-code")
2327   DECLARE_HYDROGEN_ACCESSOR(StringCharFromCode)
2328 };
2329
2330
2331 class LCheckValue V8_FINAL : public LTemplateInstruction<0, 1, 0> {
2332  public:
2333   explicit LCheckValue(LOperand* value) {
2334     inputs_[0] = value;
2335   }
2336
2337   LOperand* value() { return inputs_[0]; }
2338
2339   DECLARE_CONCRETE_INSTRUCTION(CheckValue, "check-value")
2340   DECLARE_HYDROGEN_ACCESSOR(CheckValue)
2341 };
2342
2343
2344 class LCheckInstanceType V8_FINAL : public LTemplateInstruction<0, 1, 0> {
2345  public:
2346   explicit LCheckInstanceType(LOperand* value) {
2347     inputs_[0] = value;
2348   }
2349
2350   LOperand* value() { return inputs_[0]; }
2351
2352   DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check-instance-type")
2353   DECLARE_HYDROGEN_ACCESSOR(CheckInstanceType)
2354 };
2355
2356
2357 class LCheckMaps V8_FINAL : public LTemplateInstruction<0, 1, 0> {
2358  public:
2359   explicit LCheckMaps(LOperand* value) {
2360     inputs_[0] = value;
2361   }
2362
2363   LOperand* value() { return inputs_[0]; }
2364
2365   DECLARE_CONCRETE_INSTRUCTION(CheckMaps, "check-maps")
2366   DECLARE_HYDROGEN_ACCESSOR(CheckMaps)
2367 };
2368
2369
2370 class LCheckSmi V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2371  public:
2372   explicit LCheckSmi(LOperand* value) {
2373     inputs_[0] = value;
2374   }
2375
2376   LOperand* value() { return inputs_[0]; }
2377
2378   DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check-smi")
2379 };
2380
2381
2382 class LClampDToUint8 V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2383  public:
2384   explicit LClampDToUint8(LOperand* unclamped) {
2385     inputs_[0] = unclamped;
2386   }
2387
2388   LOperand* unclamped() { return inputs_[0]; }
2389
2390   DECLARE_CONCRETE_INSTRUCTION(ClampDToUint8, "clamp-d-to-uint8")
2391 };
2392
2393
2394 class LClampIToUint8 V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2395  public:
2396   explicit LClampIToUint8(LOperand* unclamped) {
2397     inputs_[0] = unclamped;
2398   }
2399
2400   LOperand* unclamped() { return inputs_[0]; }
2401
2402   DECLARE_CONCRETE_INSTRUCTION(ClampIToUint8, "clamp-i-to-uint8")
2403 };
2404
2405
2406 class LClampTToUint8 V8_FINAL : public LTemplateInstruction<1, 1, 1> {
2407  public:
2408   LClampTToUint8(LOperand* unclamped,
2409                  LOperand* temp_xmm) {
2410     inputs_[0] = unclamped;
2411     temps_[0] = temp_xmm;
2412   }
2413
2414   LOperand* unclamped() { return inputs_[0]; }
2415   LOperand* temp_xmm() { return temps_[0]; }
2416
2417   DECLARE_CONCRETE_INSTRUCTION(ClampTToUint8, "clamp-t-to-uint8")
2418 };
2419
2420
2421 class LCheckNonSmi V8_FINAL : public LTemplateInstruction<0, 1, 0> {
2422  public:
2423   explicit LCheckNonSmi(LOperand* value) {
2424     inputs_[0] = value;
2425   }
2426
2427   LOperand* value() { return inputs_[0]; }
2428
2429   DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check-non-smi")
2430   DECLARE_HYDROGEN_ACCESSOR(CheckHeapObject)
2431 };
2432
2433
2434 class LAllocate V8_FINAL : public LTemplateInstruction<1, 2, 1> {
2435  public:
2436   LAllocate(LOperand* context, LOperand* size, LOperand* temp) {
2437     inputs_[0] = context;
2438     inputs_[1] = size;
2439     temps_[0] = temp;
2440   }
2441
2442   LOperand* context() { return inputs_[0]; }
2443   LOperand* size() { return inputs_[1]; }
2444   LOperand* temp() { return temps_[0]; }
2445
2446   DECLARE_CONCRETE_INSTRUCTION(Allocate, "allocate")
2447   DECLARE_HYDROGEN_ACCESSOR(Allocate)
2448 };
2449
2450
2451 class LRegExpLiteral V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2452  public:
2453   explicit LRegExpLiteral(LOperand* context) {
2454     inputs_[0] = context;
2455   }
2456
2457   LOperand* context() { return inputs_[0]; }
2458
2459   DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp-literal")
2460   DECLARE_HYDROGEN_ACCESSOR(RegExpLiteral)
2461 };
2462
2463
2464 class LFunctionLiteral V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2465  public:
2466   explicit LFunctionLiteral(LOperand* context) {
2467     inputs_[0] = context;
2468   }
2469
2470   LOperand* context() { return inputs_[0]; }
2471
2472   DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function-literal")
2473   DECLARE_HYDROGEN_ACCESSOR(FunctionLiteral)
2474 };
2475
2476
2477 class LToFastProperties V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2478  public:
2479   explicit LToFastProperties(LOperand* value) {
2480     inputs_[0] = value;
2481   }
2482
2483   LOperand* value() { return inputs_[0]; }
2484
2485   DECLARE_CONCRETE_INSTRUCTION(ToFastProperties, "to-fast-properties")
2486   DECLARE_HYDROGEN_ACCESSOR(ToFastProperties)
2487 };
2488
2489
2490 class LTypeof V8_FINAL : public LTemplateInstruction<1, 2, 0> {
2491  public:
2492   LTypeof(LOperand* context, LOperand* value) {
2493     inputs_[0] = context;
2494     inputs_[1] = value;
2495   }
2496
2497   LOperand* context() { return inputs_[0]; }
2498   LOperand* value() { return inputs_[1]; }
2499
2500   DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
2501 };
2502
2503
2504 class LTypeofIsAndBranch V8_FINAL : public LControlInstruction<1, 0> {
2505  public:
2506   explicit LTypeofIsAndBranch(LOperand* value) {
2507     inputs_[0] = value;
2508   }
2509
2510   LOperand* value() { return inputs_[0]; }
2511
2512   DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch, "typeof-is-and-branch")
2513   DECLARE_HYDROGEN_ACCESSOR(TypeofIsAndBranch)
2514
2515   Handle<String> type_literal() { return hydrogen()->type_literal(); }
2516
2517   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
2518 };
2519
2520
2521 class LIsConstructCallAndBranch V8_FINAL : public LControlInstruction<0, 1> {
2522  public:
2523   explicit LIsConstructCallAndBranch(LOperand* temp) {
2524     temps_[0] = temp;
2525   }
2526
2527   LOperand* temp() { return temps_[0]; }
2528
2529   DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch,
2530                                "is-construct-call-and-branch")
2531   DECLARE_HYDROGEN_ACCESSOR(IsConstructCallAndBranch)
2532 };
2533
2534
2535 class LOsrEntry V8_FINAL : public LTemplateInstruction<0, 0, 0> {
2536  public:
2537   LOsrEntry() {}
2538
2539   virtual bool HasInterestingComment(LCodeGen* gen) const V8_OVERRIDE {
2540     return false;
2541   }
2542   DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr-entry")
2543 };
2544
2545
2546 class LStackCheck V8_FINAL : public LTemplateInstruction<0, 1, 0> {
2547  public:
2548   explicit LStackCheck(LOperand* context) {
2549     inputs_[0] = context;
2550   }
2551
2552   LOperand* context() { return inputs_[0]; }
2553
2554   DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack-check")
2555   DECLARE_HYDROGEN_ACCESSOR(StackCheck)
2556
2557   Label* done_label() { return &done_label_; }
2558
2559  private:
2560   Label done_label_;
2561 };
2562
2563
2564 class LForInPrepareMap V8_FINAL : public LTemplateInstruction<1, 2, 0> {
2565  public:
2566   LForInPrepareMap(LOperand* context, LOperand* object) {
2567     inputs_[0] = context;
2568     inputs_[1] = object;
2569   }
2570
2571   LOperand* context() { return inputs_[0]; }
2572   LOperand* object() { return inputs_[1]; }
2573
2574   DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap, "for-in-prepare-map")
2575 };
2576
2577
2578 class LForInCacheArray V8_FINAL : public LTemplateInstruction<1, 1, 0> {
2579  public:
2580   explicit LForInCacheArray(LOperand* map) {
2581     inputs_[0] = map;
2582   }
2583
2584   LOperand* map() { return inputs_[0]; }
2585
2586   DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray, "for-in-cache-array")
2587
2588   int idx() {
2589     return HForInCacheArray::cast(this->hydrogen_value())->idx();
2590   }
2591 };
2592
2593
2594 class LCheckMapValue V8_FINAL : public LTemplateInstruction<0, 2, 0> {
2595  public:
2596   LCheckMapValue(LOperand* value, LOperand* map) {
2597     inputs_[0] = value;
2598     inputs_[1] = map;
2599   }
2600
2601   LOperand* value() { return inputs_[0]; }
2602   LOperand* map() { return inputs_[1]; }
2603
2604   DECLARE_CONCRETE_INSTRUCTION(CheckMapValue, "check-map-value")
2605 };
2606
2607
2608 class LLoadFieldByIndex V8_FINAL : public LTemplateInstruction<1, 2, 0> {
2609  public:
2610   LLoadFieldByIndex(LOperand* object, LOperand* index) {
2611     inputs_[0] = object;
2612     inputs_[1] = index;
2613   }
2614
2615   LOperand* object() { return inputs_[0]; }
2616   LOperand* index() { return inputs_[1]; }
2617
2618   DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex, "load-field-by-index")
2619 };
2620
2621
2622 class LChunkBuilder;
2623 class LPlatformChunk V8_FINAL : public LChunk {
2624  public:
2625   LPlatformChunk(CompilationInfo* info, HGraph* graph)
2626       : LChunk(info, graph) { }
2627
2628   int GetNextSpillIndex(RegisterKind kind);
2629   LOperand* GetNextSpillSlot(RegisterKind kind);
2630 };
2631
2632
2633 class LChunkBuilder V8_FINAL : public LChunkBuilderBase {
2634  public:
2635   LChunkBuilder(CompilationInfo* info, HGraph* graph, LAllocator* allocator)
2636       : LChunkBuilderBase(graph->zone()),
2637         chunk_(NULL),
2638         info_(info),
2639         graph_(graph),
2640         status_(UNUSED),
2641         current_instruction_(NULL),
2642         current_block_(NULL),
2643         next_block_(NULL),
2644         allocator_(allocator),
2645         instruction_pending_deoptimization_environment_(NULL),
2646         pending_deoptimization_ast_id_(BailoutId::None()) { }
2647
2648   // Build the sequence for the graph.
2649   LPlatformChunk* Build();
2650
2651   LInstruction* CheckElideControlInstruction(HControlInstruction* instr);
2652
2653   // Declare methods that deal with the individual node types.
2654 #define DECLARE_DO(type) LInstruction* Do##type(H##type* node);
2655   HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
2656 #undef DECLARE_DO
2657
2658   static HValue* SimplifiedDivisorForMathFloorOfDiv(HValue* val);
2659
2660   LInstruction* DoMathFloor(HUnaryMathOperation* instr);
2661   LInstruction* DoMathRound(HUnaryMathOperation* instr);
2662   LInstruction* DoMathAbs(HUnaryMathOperation* instr);
2663   LInstruction* DoMathLog(HUnaryMathOperation* instr);
2664   LInstruction* DoMathExp(HUnaryMathOperation* instr);
2665   LInstruction* DoMathSqrt(HUnaryMathOperation* instr);
2666   LInstruction* DoMathPowHalf(HUnaryMathOperation* instr);
2667
2668  private:
2669   enum Status {
2670     UNUSED,
2671     BUILDING,
2672     DONE,
2673     ABORTED
2674   };
2675
2676   LPlatformChunk* chunk() const { return chunk_; }
2677   CompilationInfo* info() const { return info_; }
2678   HGraph* graph() const { return graph_; }
2679
2680   bool is_unused() const { return status_ == UNUSED; }
2681   bool is_building() const { return status_ == BUILDING; }
2682   bool is_done() const { return status_ == DONE; }
2683   bool is_aborted() const { return status_ == ABORTED; }
2684
2685   void Abort(BailoutReason reason);
2686
2687   // Methods for getting operands for Use / Define / Temp.
2688   LUnallocated* ToUnallocated(Register reg);
2689   LUnallocated* ToUnallocated(XMMRegister reg);
2690
2691   // Methods for setting up define-use relationships.
2692   MUST_USE_RESULT LOperand* Use(HValue* value, LUnallocated* operand);
2693   MUST_USE_RESULT LOperand* UseFixed(HValue* value, Register fixed_register);
2694   MUST_USE_RESULT LOperand* UseFixedDouble(HValue* value,
2695                                            XMMRegister fixed_register);
2696
2697   // A value that is guaranteed to be allocated to a register.
2698   // Operand created by UseRegister is guaranteed to be live until the end of
2699   // instruction. This means that register allocator will not reuse it's
2700   // register for any other operand inside instruction.
2701   // Operand created by UseRegisterAtStart is guaranteed to be live only at
2702   // instruction start. Register allocator is free to assign the same register
2703   // to some other operand used inside instruction (i.e. temporary or
2704   // output).
2705   MUST_USE_RESULT LOperand* UseRegister(HValue* value);
2706   MUST_USE_RESULT LOperand* UseRegisterAtStart(HValue* value);
2707
2708   // An input operand in a register that may be trashed.
2709   MUST_USE_RESULT LOperand* UseTempRegister(HValue* value);
2710
2711   // An input operand in a register that may be trashed or a constant operand.
2712   MUST_USE_RESULT LOperand* UseTempRegisterOrConstant(HValue* value);
2713
2714   // An input operand in a register or stack slot.
2715   MUST_USE_RESULT LOperand* Use(HValue* value);
2716   MUST_USE_RESULT LOperand* UseAtStart(HValue* value);
2717
2718   // An input operand in a register, stack slot or a constant operand.
2719   MUST_USE_RESULT LOperand* UseOrConstant(HValue* value);
2720   MUST_USE_RESULT LOperand* UseOrConstantAtStart(HValue* value);
2721
2722   // An input operand in a register or a constant operand.
2723   MUST_USE_RESULT LOperand* UseRegisterOrConstant(HValue* value);
2724   MUST_USE_RESULT LOperand* UseRegisterOrConstantAtStart(HValue* value);
2725
2726   // An input operand in a constant operand.
2727   MUST_USE_RESULT LOperand* UseConstant(HValue* value);
2728
2729   // An input operand in register, stack slot or a constant operand.
2730   // Will not be moved to a register even if one is freely available.
2731   virtual MUST_USE_RESULT LOperand* UseAny(HValue* value) V8_OVERRIDE;
2732
2733   // Temporary operand that must be in a register.
2734   MUST_USE_RESULT LUnallocated* TempRegister();
2735   MUST_USE_RESULT LOperand* FixedTemp(Register reg);
2736   MUST_USE_RESULT LOperand* FixedTemp(XMMRegister reg);
2737
2738   // Methods for setting up define-use relationships.
2739   // Return the same instruction that they are passed.
2740   template<int I, int T>
2741       LInstruction* Define(LTemplateInstruction<1, I, T>* instr,
2742                            LUnallocated* result);
2743   template<int I, int T>
2744       LInstruction* DefineAsRegister(LTemplateInstruction<1, I, T>* instr);
2745   template<int I, int T>
2746       LInstruction* DefineAsSpilled(LTemplateInstruction<1, I, T>* instr,
2747                                     int index);
2748   template<int I, int T>
2749       LInstruction* DefineSameAsFirst(LTemplateInstruction<1, I, T>* instr);
2750   template<int I, int T>
2751       LInstruction* DefineFixed(LTemplateInstruction<1, I, T>* instr,
2752                                 Register reg);
2753   template<int I, int T>
2754       LInstruction* DefineFixedDouble(LTemplateInstruction<1, I, T>* instr,
2755                                       XMMRegister reg);
2756   // Assigns an environment to an instruction.  An instruction which can
2757   // deoptimize must have an environment.
2758   LInstruction* AssignEnvironment(LInstruction* instr);
2759   // Assigns a pointer map to an instruction.  An instruction which can
2760   // trigger a GC or a lazy deoptimization must have a pointer map.
2761   LInstruction* AssignPointerMap(LInstruction* instr);
2762
2763   enum CanDeoptimize { CAN_DEOPTIMIZE_EAGERLY, CANNOT_DEOPTIMIZE_EAGERLY };
2764
2765   // Marks a call for the register allocator.  Assigns a pointer map to
2766   // support GC and lazy deoptimization.  Assigns an environment to support
2767   // eager deoptimization if CAN_DEOPTIMIZE_EAGERLY.
2768   LInstruction* MarkAsCall(
2769       LInstruction* instr,
2770       HInstruction* hinstr,
2771       CanDeoptimize can_deoptimize = CANNOT_DEOPTIMIZE_EAGERLY);
2772
2773   void VisitInstruction(HInstruction* current);
2774
2775   void DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block);
2776   LInstruction* DoShift(Token::Value op, HBitwiseBinaryOperation* instr);
2777   LInstruction* DoArithmeticD(Token::Value op,
2778                               HArithmeticBinaryOperation* instr);
2779   LInstruction* DoArithmeticT(Token::Value op,
2780                               HBinaryOperation* instr);
2781
2782   LPlatformChunk* chunk_;
2783   CompilationInfo* info_;
2784   HGraph* const graph_;
2785   Status status_;
2786   HInstruction* current_instruction_;
2787   HBasicBlock* current_block_;
2788   HBasicBlock* next_block_;
2789   LAllocator* allocator_;
2790   LInstruction* instruction_pending_deoptimization_environment_;
2791   BailoutId pending_deoptimization_ast_id_;
2792
2793   DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
2794 };
2795
2796 #undef DECLARE_HYDROGEN_ACCESSOR
2797 #undef DECLARE_CONCRETE_INSTRUCTION
2798
2799 } }  // namespace v8::int
2800
2801 #endif  // V8_X64_LITHIUM_X64_H_