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