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