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