V8 Project
lithium-arm64.h
Go to the documentation of this file.
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_ARM64_LITHIUM_ARM64_H_
6 #define V8_ARM64_LITHIUM_ARM64_H_
7 
8 #include "src/hydrogen.h"
9 #include "src/lithium.h"
10 #include "src/lithium-allocator.h"
11 #include "src/safepoint-table.h"
12 #include "src/utils.h"
13 
14 namespace v8 {
15 namespace internal {
16 
17 // Forward declarations.
18 class LCodeGen;
19 
20 #define LITHIUM_CONCRETE_INSTRUCTION_LIST(V) \
21  V(AccessArgumentsAt) \
22  V(AddE) \
23  V(AddI) \
24  V(AddS) \
25  V(Allocate) \
26  V(AllocateBlockContext) \
27  V(ApplyArguments) \
28  V(ArgumentsElements) \
29  V(ArgumentsLength) \
30  V(ArithmeticD) \
31  V(ArithmeticT) \
32  V(BitI) \
33  V(BitS) \
34  V(BoundsCheck) \
35  V(Branch) \
36  V(CallFunction) \
37  V(CallJSFunction) \
38  V(CallNew) \
39  V(CallNewArray) \
40  V(CallRuntime) \
41  V(CallStub) \
42  V(CallWithDescriptor) \
43  V(CheckInstanceType) \
44  V(CheckMapValue) \
45  V(CheckMaps) \
46  V(CheckNonSmi) \
47  V(CheckSmi) \
48  V(CheckValue) \
49  V(ClampDToUint8) \
50  V(ClampIToUint8) \
51  V(ClampTToUint8) \
52  V(ClassOfTestAndBranch) \
53  V(CmpHoleAndBranchD) \
54  V(CmpHoleAndBranchT) \
55  V(CmpMapAndBranch) \
56  V(CmpObjectEqAndBranch) \
57  V(CmpT) \
58  V(CompareMinusZeroAndBranch) \
59  V(CompareNumericAndBranch) \
60  V(ConstantD) \
61  V(ConstantE) \
62  V(ConstantI) \
63  V(ConstantS) \
64  V(ConstantT) \
65  V(ConstructDouble) \
66  V(Context) \
67  V(DateField) \
68  V(DebugBreak) \
69  V(DeclareGlobals) \
70  V(Deoptimize) \
71  V(DivByConstI) \
72  V(DivByPowerOf2I) \
73  V(DivI) \
74  V(DoubleBits) \
75  V(DoubleToIntOrSmi) \
76  V(Drop) \
77  V(Dummy) \
78  V(DummyUse) \
79  V(FlooringDivByConstI) \
80  V(FlooringDivByPowerOf2I) \
81  V(FlooringDivI) \
82  V(ForInCacheArray) \
83  V(ForInPrepareMap) \
84  V(FunctionLiteral) \
85  V(GetCachedArrayIndex) \
86  V(Goto) \
87  V(HasCachedArrayIndexAndBranch) \
88  V(HasInstanceTypeAndBranch) \
89  V(InnerAllocatedObject) \
90  V(InstanceOf) \
91  V(InstanceOfKnownGlobal) \
92  V(InstructionGap) \
93  V(Integer32ToDouble) \
94  V(InvokeFunction) \
95  V(IsConstructCallAndBranch) \
96  V(IsObjectAndBranch) \
97  V(IsSmiAndBranch) \
98  V(IsStringAndBranch) \
99  V(IsUndetectableAndBranch) \
100  V(Label) \
101  V(LazyBailout) \
102  V(LoadContextSlot) \
103  V(LoadFieldByIndex) \
104  V(LoadFunctionPrototype) \
105  V(LoadGlobalCell) \
106  V(LoadGlobalGeneric) \
107  V(LoadKeyedExternal) \
108  V(LoadKeyedFixed) \
109  V(LoadKeyedFixedDouble) \
110  V(LoadKeyedGeneric) \
111  V(LoadNamedField) \
112  V(LoadNamedGeneric) \
113  V(LoadRoot) \
114  V(MapEnumLength) \
115  V(MathAbs) \
116  V(MathAbsTagged) \
117  V(MathClz32) \
118  V(MathExp) \
119  V(MathFloorD) \
120  V(MathFloorI) \
121  V(MathFround) \
122  V(MathLog) \
123  V(MathMinMax) \
124  V(MathPowHalf) \
125  V(MathRoundD) \
126  V(MathRoundI) \
127  V(MathSqrt) \
128  V(ModByConstI) \
129  V(ModByPowerOf2I) \
130  V(ModI) \
131  V(MulConstIS) \
132  V(MulI) \
133  V(MulS) \
134  V(NumberTagD) \
135  V(NumberTagU) \
136  V(NumberUntagD) \
137  V(OsrEntry) \
138  V(Parameter) \
139  V(Power) \
140  V(PreparePushArguments) \
141  V(PushArguments) \
142  V(RegExpLiteral) \
143  V(Return) \
144  V(SeqStringGetChar) \
145  V(SeqStringSetChar) \
146  V(ShiftI) \
147  V(ShiftS) \
148  V(SmiTag) \
149  V(SmiUntag) \
150  V(StackCheck) \
151  V(StoreCodeEntry) \
152  V(StoreContextSlot) \
153  V(StoreFrameContext) \
154  V(StoreGlobalCell) \
155  V(StoreKeyedExternal) \
156  V(StoreKeyedFixed) \
157  V(StoreKeyedFixedDouble) \
158  V(StoreKeyedGeneric) \
159  V(StoreNamedField) \
160  V(StoreNamedGeneric) \
161  V(StringAdd) \
162  V(StringCharCodeAt) \
163  V(StringCharFromCode) \
164  V(StringCompareAndBranch) \
165  V(SubI) \
166  V(SubS) \
167  V(TaggedToI) \
168  V(TailCallThroughMegamorphicCache) \
169  V(ThisFunction) \
170  V(ToFastProperties) \
171  V(TransitionElementsKind) \
172  V(TrapAllocationMemento) \
173  V(TruncateDoubleToIntOrSmi) \
174  V(Typeof) \
175  V(TypeofIsAndBranch) \
176  V(Uint32ToDouble) \
177  V(UnknownOSRValue) \
178  V(WrapReceiver)
179 
180 
181 #define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
182  virtual Opcode opcode() const FINAL OVERRIDE { \
183  return LInstruction::k##type; \
184  } \
185  virtual void CompileToNative(LCodeGen* generator) FINAL OVERRIDE; \
186  virtual const char* Mnemonic() const FINAL OVERRIDE { \
187  return mnemonic; \
188  } \
189  static L##type* cast(LInstruction* instr) { \
190  DCHECK(instr->Is##type()); \
191  return reinterpret_cast<L##type*>(instr); \
192  }
193 
194 
195 #define DECLARE_HYDROGEN_ACCESSOR(type) \
196  H##type* hydrogen() const { \
197  return H##type::cast(this->hydrogen_value()); \
198  }
199 
200 
201 class LInstruction : public ZoneObject {
202  public:
204  : environment_(NULL),
206  bit_field_(IsCallBits::encode(false)) { }
207 
208  virtual ~LInstruction() { }
209 
210  virtual void CompileToNative(LCodeGen* generator) = 0;
211  virtual const char* Mnemonic() const = 0;
212  virtual void PrintTo(StringStream* stream);
213  virtual void PrintDataTo(StringStream* stream);
214  virtual void PrintOutputOperandTo(StringStream* stream);
215 
216  enum Opcode {
217  // Declare a unique enum value for each instruction.
218 #define DECLARE_OPCODE(type) k##type,
221 #undef DECLARE_OPCODE
222  };
223 
224  virtual Opcode opcode() const = 0;
225 
226  // Declare non-virtual type testers for all leaf IR classes.
227 #define DECLARE_PREDICATE(type) \
228  bool Is##type() const { return opcode() == k##type; }
230 #undef DECLARE_PREDICATE
231 
232  // Declare virtual predicates for instructions that don't have
233  // an opcode.
234  virtual bool IsGap() const { return false; }
235 
236  virtual bool IsControl() const { return false; }
237 
238  // Try deleting this instruction if possible.
239  virtual bool TryDelete() { return false; }
240 
241  void set_environment(LEnvironment* env) { environment_ = env; }
242  LEnvironment* environment() const { return environment_; }
243  bool HasEnvironment() const { return environment_ != NULL; }
244 
245  void set_pointer_map(LPointerMap* p) { pointer_map_.set(p); }
246  LPointerMap* pointer_map() const { return pointer_map_.get(); }
247  bool HasPointerMap() const { return pointer_map_.is_set(); }
248 
249  void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; }
250  HValue* hydrogen_value() const { return hydrogen_value_; }
251 
252  virtual void SetDeferredLazyDeoptimizationEnvironment(LEnvironment* env) { }
253 
255  bool IsCall() const { return IsCallBits::decode(bit_field_); }
256 
257  // Interface to the register allocator and iterators.
258  bool ClobbersTemps() const { return IsCall(); }
259  bool ClobbersRegisters() const { return IsCall(); }
260  virtual bool ClobbersDoubleRegisters(Isolate* isolate) const {
261  return IsCall();
262  }
263  bool IsMarkedAsCall() const { return IsCall(); }
264 
265  virtual bool HasResult() const = 0;
266  virtual LOperand* result() const = 0;
267 
268  virtual int InputCount() = 0;
269  virtual LOperand* InputAt(int i) = 0;
270  virtual int TempCount() = 0;
271  virtual LOperand* TempAt(int i) = 0;
272 
273  LOperand* FirstInput() { return InputAt(0); }
274  LOperand* Output() { return HasResult() ? result() : NULL; }
275 
276  virtual bool HasInterestingComment(LCodeGen* gen) const { return true; }
277 
278 #ifdef DEBUG
279  void VerifyCall();
280 #endif
281 
282  private:
283  class IsCallBits: public BitField<bool, 0, 1> {};
284 
285  LEnvironment* environment_;
286  SetOncePointer<LPointerMap> pointer_map_;
287  HValue* hydrogen_value_;
289 };
290 
291 
292 // R = number of result operands (0 or 1).
293 template<int R>
295  public:
296  // Allow 0 or 1 output operands.
297  STATIC_ASSERT(R == 0 || R == 1);
298  virtual bool HasResult() const FINAL OVERRIDE {
299  return (R != 0) && (result() != NULL);
300  }
301  void set_result(LOperand* operand) { results_[0] = operand; }
302  LOperand* result() const { return results_[0]; }
303 
304  protected:
306 };
307 
308 
309 // R = number of result operands (0 or 1).
310 // I = number of input operands.
311 // T = number of temporary operands.
312 template<int R, int I, int T>
313 class LTemplateInstruction : public LTemplateResultInstruction<R> {
314  protected:
315  EmbeddedContainer<LOperand*, I> inputs_;
316  EmbeddedContainer<LOperand*, T> temps_;
317 
318  private:
319  // Iterator support.
320  virtual int InputCount() FINAL OVERRIDE { return I; }
321  virtual LOperand* InputAt(int i) FINAL OVERRIDE { return inputs_[i]; }
322 
323  virtual int TempCount() FINAL OVERRIDE { return T; }
324  virtual LOperand* TempAt(int i) FINAL OVERRIDE { return temps_[i]; }
325 };
326 
327 
328 class LTailCallThroughMegamorphicCache FINAL
329  : public LTemplateInstruction<0, 3, 0> {
330  public:
332  LOperand* receiver,
333  LOperand* name) {
334  inputs_[0] = context;
335  inputs_[1] = receiver;
336  inputs_[2] = name;
337  }
338 
339  LOperand* context() { return inputs_[0]; }
340  LOperand* receiver() { return inputs_[1]; }
341  LOperand* name() { return inputs_[2]; }
342 
343  DECLARE_CONCRETE_INSTRUCTION(TailCallThroughMegamorphicCache,
344  "tail-call-through-megamorphic-cache")
345  DECLARE_HYDROGEN_ACCESSOR(TailCallThroughMegamorphicCache)
346 };
347 
348 
349 class LUnknownOSRValue FINAL : public LTemplateInstruction<1, 0, 0> {
350  public:
351  virtual bool HasInterestingComment(LCodeGen* gen) const OVERRIDE {
352  return false;
353  }
354  DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown-osr-value")
355 };
356 
357 
358 template<int I, int T>
359 class LControlInstruction : public LTemplateInstruction<0, I, T> {
360  public:
361  LControlInstruction() : false_label_(NULL), true_label_(NULL) { }
362 
363  virtual bool IsControl() const FINAL OVERRIDE { return true; }
364 
365  int SuccessorCount() { return hydrogen()->SuccessorCount(); }
366  HBasicBlock* SuccessorAt(int i) { return hydrogen()->SuccessorAt(i); }
367 
368  int TrueDestination(LChunk* chunk) {
369  return chunk->LookupDestination(true_block_id());
370  }
371 
372  int FalseDestination(LChunk* chunk) {
373  return chunk->LookupDestination(false_block_id());
374  }
375 
376  Label* TrueLabel(LChunk* chunk) {
377  if (true_label_ == NULL) {
378  true_label_ = chunk->GetAssemblyLabel(TrueDestination(chunk));
379  }
380  return true_label_;
381  }
382 
383  Label* FalseLabel(LChunk* chunk) {
384  if (false_label_ == NULL) {
385  false_label_ = chunk->GetAssemblyLabel(FalseDestination(chunk));
386  }
387  return false_label_;
388  }
389 
390  protected:
391  int true_block_id() { return SuccessorAt(0)->block_id(); }
392  int false_block_id() { return SuccessorAt(1)->block_id(); }
393 
394  private:
395  DECLARE_HYDROGEN_ACCESSOR(ControlInstruction);
396 
397  Label* false_label_;
398  Label* true_label_;
399 };
400 
401 
402 class LGap : public LTemplateInstruction<0, 0, 0> {
403  public:
404  explicit LGap(HBasicBlock* block)
405  : block_(block) {
406  parallel_moves_[BEFORE] = NULL;
407  parallel_moves_[START] = NULL;
408  parallel_moves_[END] = NULL;
409  parallel_moves_[AFTER] = NULL;
410  }
411 
412  // Can't use the DECLARE-macro here because of sub-classes.
413  virtual bool IsGap() const OVERRIDE { return true; }
414  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
415  static LGap* cast(LInstruction* instr) {
416  DCHECK(instr->IsGap());
417  return reinterpret_cast<LGap*>(instr);
418  }
419 
420  bool IsRedundant() const;
421 
422  HBasicBlock* block() const { return block_; }
423 
425  BEFORE,
426  START,
427  END,
428  AFTER,
429  FIRST_INNER_POSITION = BEFORE,
430  LAST_INNER_POSITION = AFTER
431  };
432 
433  LParallelMove* GetOrCreateParallelMove(InnerPosition pos, Zone* zone) {
434  if (parallel_moves_[pos] == NULL) {
435  parallel_moves_[pos] = new(zone) LParallelMove(zone);
436  }
437  return parallel_moves_[pos];
438  }
439 
440  LParallelMove* GetParallelMove(InnerPosition pos) {
441  return parallel_moves_[pos];
442  }
443 
444  private:
445  LParallelMove* parallel_moves_[LAST_INNER_POSITION + 1];
446  HBasicBlock* block_;
447 };
448 
449 
450 class LInstructionGap FINAL : public LGap {
451  public:
452  explicit LInstructionGap(HBasicBlock* block) : LGap(block) { }
453 
454  virtual bool HasInterestingComment(LCodeGen* gen) const OVERRIDE {
455  return !IsRedundant();
456  }
457 
458  DECLARE_CONCRETE_INSTRUCTION(InstructionGap, "gap")
459 };
460 
461 
462 class LDrop FINAL : public LTemplateInstruction<0, 0, 0> {
463  public:
464  explicit LDrop(int count) : count_(count) { }
465 
466  int count() const { return count_; }
467 
468  DECLARE_CONCRETE_INSTRUCTION(Drop, "drop")
469 
470  private:
471  int count_;
472 };
473 
474 
475 class LDummy FINAL : public LTemplateInstruction<1, 0, 0> {
476  public:
477  LDummy() {}
478  DECLARE_CONCRETE_INSTRUCTION(Dummy, "dummy")
479 };
480 
481 
482 class LDummyUse FINAL : public LTemplateInstruction<1, 1, 0> {
483  public:
484  explicit LDummyUse(LOperand* value) {
485  inputs_[0] = value;
486  }
487  DECLARE_CONCRETE_INSTRUCTION(DummyUse, "dummy-use")
488 };
489 
490 
491 class LGoto FINAL : public LTemplateInstruction<0, 0, 0> {
492  public:
493  explicit LGoto(HBasicBlock* block) : block_(block) { }
494 
495  virtual bool HasInterestingComment(LCodeGen* gen) const OVERRIDE;
496  DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
497  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
498  virtual bool IsControl() const OVERRIDE { return true; }
499 
500  int block_id() const { return block_->block_id(); }
501 
502  private:
503  HBasicBlock* block_;
504 };
505 
506 
507 class LLazyBailout FINAL : public LTemplateInstruction<0, 0, 0> {
508  public:
509  LLazyBailout() : gap_instructions_size_(0) { }
510 
511  DECLARE_CONCRETE_INSTRUCTION(LazyBailout, "lazy-bailout")
512 
513  void set_gap_instructions_size(int gap_instructions_size) {
514  gap_instructions_size_ = gap_instructions_size;
515  }
516  int gap_instructions_size() { return gap_instructions_size_; }
517 
518  private:
519  int gap_instructions_size_;
520 };
521 
522 
523 class LLabel FINAL : public LGap {
524  public:
525  explicit LLabel(HBasicBlock* block)
526  : LGap(block), replacement_(NULL) { }
527 
528  virtual bool HasInterestingComment(LCodeGen* gen) const OVERRIDE {
529  return false;
530  }
531  DECLARE_CONCRETE_INSTRUCTION(Label, "label")
532 
533  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
534 
535  int block_id() const { return block()->block_id(); }
536  bool is_loop_header() const { return block()->IsLoopHeader(); }
537  bool is_osr_entry() const { return block()->is_osr_entry(); }
538  Label* label() { return &label_; }
539  LLabel* replacement() const { return replacement_; }
540  void set_replacement(LLabel* label) { replacement_ = label; }
541  bool HasReplacement() const { return replacement_ != NULL; }
542 
543  private:
544  Label label_;
545  LLabel* replacement_;
546 };
547 
548 
549 class LOsrEntry FINAL : public LTemplateInstruction<0, 0, 0> {
550  public:
552 
553  virtual bool HasInterestingComment(LCodeGen* gen) const OVERRIDE {
554  return false;
555  }
556  DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr-entry")
557 };
558 
559 
560 class LAccessArgumentsAt FINAL : public LTemplateInstruction<1, 3, 0> {
561  public:
563  LOperand* length,
564  LOperand* index) {
565  inputs_[0] = arguments;
566  inputs_[1] = length;
567  inputs_[2] = index;
568  }
569 
570  DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access-arguments-at")
571 
572  LOperand* arguments() { return inputs_[0]; }
573  LOperand* length() { return inputs_[1]; }
574  LOperand* index() { return inputs_[2]; }
575 
576  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
577 };
578 
579 
580 class LAddE FINAL : public LTemplateInstruction<1, 2, 0> {
581  public:
582  LAddE(LOperand* left, LOperand* right) {
583  inputs_[0] = left;
584  inputs_[1] = right;
585  }
586 
587  LOperand* left() { return inputs_[0]; }
588  LOperand* right() { return inputs_[1]; }
589 
590  DECLARE_CONCRETE_INSTRUCTION(AddE, "add-e")
592 };
593 
594 
595 class LAddI FINAL : public LTemplateInstruction<1, 2, 0> {
596  public:
597  LAddI(LOperand* left, LOperand* right)
598  : shift_(NO_SHIFT), shift_amount_(0) {
599  inputs_[0] = left;
600  inputs_[1] = right;
601  }
602 
603  LAddI(LOperand* left, LOperand* right, Shift shift, LOperand* shift_amount)
604  : shift_(shift), shift_amount_(shift_amount) {
605  inputs_[0] = left;
606  inputs_[1] = right;
607  }
608 
609  LOperand* left() { return inputs_[0]; }
610  LOperand* right() { return inputs_[1]; }
611 
612  Shift shift() const { return shift_; }
613  LOperand* shift_amount() const { return shift_amount_; }
614 
615  DECLARE_CONCRETE_INSTRUCTION(AddI, "add-i")
617 
618  protected:
619  Shift shift_;
620  LOperand* shift_amount_;
621 };
622 
623 
624 class LAddS FINAL : public LTemplateInstruction<1, 2, 0> {
625  public:
626  LAddS(LOperand* left, LOperand* right) {
627  inputs_[0] = left;
628  inputs_[1] = right;
629  }
630 
631  LOperand* left() { return inputs_[0]; }
632  LOperand* right() { return inputs_[1]; }
633 
634  DECLARE_CONCRETE_INSTRUCTION(AddS, "add-s")
636 };
637 
638 
639 class LAllocate FINAL : public LTemplateInstruction<1, 2, 3> {
640  public:
641  LAllocate(LOperand* context,
642  LOperand* size,
643  LOperand* temp1,
644  LOperand* temp2,
645  LOperand* temp3) {
646  inputs_[0] = context;
647  inputs_[1] = size;
648  temps_[0] = temp1;
649  temps_[1] = temp2;
650  temps_[2] = temp3;
651  }
652 
653  LOperand* context() { return inputs_[0]; }
654  LOperand* size() { return inputs_[1]; }
655  LOperand* temp1() { return temps_[0]; }
656  LOperand* temp2() { return temps_[1]; }
657  LOperand* temp3() { return temps_[2]; }
658 
659  DECLARE_CONCRETE_INSTRUCTION(Allocate, "allocate")
660  DECLARE_HYDROGEN_ACCESSOR(Allocate)
661 };
662 
663 
664 class LApplyArguments FINAL : public LTemplateInstruction<1, 4, 0> {
665  public:
667  LOperand* receiver,
668  LOperand* length,
669  LOperand* elements) {
670  inputs_[0] = function;
671  inputs_[1] = receiver;
672  inputs_[2] = length;
673  inputs_[3] = elements;
674  }
675 
676  DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply-arguments")
677 
678  LOperand* function() { return inputs_[0]; }
679  LOperand* receiver() { return inputs_[1]; }
680  LOperand* length() { return inputs_[2]; }
681  LOperand* elements() { return inputs_[3]; }
682 };
683 
684 
685 class LArgumentsElements FINAL : public LTemplateInstruction<1, 0, 1> {
686  public:
687  explicit LArgumentsElements(LOperand* temp) {
688  temps_[0] = temp;
689  }
690 
691  LOperand* temp() { return temps_[0]; }
692 
693  DECLARE_CONCRETE_INSTRUCTION(ArgumentsElements, "arguments-elements")
694  DECLARE_HYDROGEN_ACCESSOR(ArgumentsElements)
695 };
696 
697 
698 class LArgumentsLength FINAL : public LTemplateInstruction<1, 1, 0> {
699  public:
700  explicit LArgumentsLength(LOperand* elements) {
701  inputs_[0] = elements;
702  }
703 
704  LOperand* elements() { return inputs_[0]; }
705 
706  DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments-length")
707 };
708 
709 
710 class LArithmeticD FINAL : public LTemplateInstruction<1, 2, 0> {
711  public:
713  LOperand* left,
714  LOperand* right)
715  : op_(op) {
716  inputs_[0] = left;
717  inputs_[1] = right;
718  }
719 
720  Token::Value op() const { return op_; }
721  LOperand* left() { return inputs_[0]; }
722  LOperand* right() { return inputs_[1]; }
723 
724  virtual Opcode opcode() const OVERRIDE {
725  return LInstruction::kArithmeticD;
726  }
727  virtual void CompileToNative(LCodeGen* generator) OVERRIDE;
728  virtual const char* Mnemonic() const OVERRIDE;
729 
730  private:
731  Token::Value op_;
732 };
733 
734 
735 class LArithmeticT FINAL : public LTemplateInstruction<1, 3, 0> {
736  public:
738  LOperand* context,
739  LOperand* left,
740  LOperand* right)
741  : op_(op) {
742  inputs_[0] = context;
743  inputs_[1] = left;
744  inputs_[2] = right;
745  }
746 
747  LOperand* context() { return inputs_[0]; }
748  LOperand* left() { return inputs_[1]; }
749  LOperand* right() { return inputs_[2]; }
750  Token::Value op() const { return op_; }
751 
752  virtual Opcode opcode() const OVERRIDE {
753  return LInstruction::kArithmeticT;
754  }
755  virtual void CompileToNative(LCodeGen* generator) OVERRIDE;
756  virtual const char* Mnemonic() const OVERRIDE;
757 
758  private:
759  Token::Value op_;
760 };
761 
762 
763 class LBoundsCheck FINAL : public LTemplateInstruction<0, 2, 0> {
764  public:
765  explicit LBoundsCheck(LOperand* index, LOperand* length) {
766  inputs_[0] = index;
767  inputs_[1] = length;
768  }
769 
770  LOperand* index() { return inputs_[0]; }
771  LOperand* length() { return inputs_[1]; }
772 
773  DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check")
774  DECLARE_HYDROGEN_ACCESSOR(BoundsCheck)
775 };
776 
777 
778 class LBitI FINAL : public LTemplateInstruction<1, 2, 0> {
779  public:
780  LBitI(LOperand* left, LOperand* right)
781  : shift_(NO_SHIFT), shift_amount_(0) {
782  inputs_[0] = left;
783  inputs_[1] = right;
784  }
785 
786  LBitI(LOperand* left, LOperand* right, Shift shift, LOperand* shift_amount)
787  : shift_(shift), shift_amount_(shift_amount) {
788  inputs_[0] = left;
789  inputs_[1] = right;
790  }
791 
792  LOperand* left() { return inputs_[0]; }
793  LOperand* right() { return inputs_[1]; }
794 
795  Shift shift() const { return shift_; }
796  LOperand* shift_amount() const { return shift_amount_; }
797 
798  Token::Value op() const { return hydrogen()->op(); }
799 
800  DECLARE_CONCRETE_INSTRUCTION(BitI, "bit-i")
802 
803  protected:
804  Shift shift_;
805  LOperand* shift_amount_;
806 };
807 
808 
809 class LBitS FINAL : public LTemplateInstruction<1, 2, 0> {
810  public:
811  LBitS(LOperand* left, LOperand* right) {
812  inputs_[0] = left;
813  inputs_[1] = right;
814  }
815 
816  LOperand* left() { return inputs_[0]; }
817  LOperand* right() { return inputs_[1]; }
818 
819  Token::Value op() const { return hydrogen()->op(); }
820 
821  DECLARE_CONCRETE_INSTRUCTION(BitS, "bit-s")
823 };
824 
825 
826 class LBranch FINAL : public LControlInstruction<1, 2> {
827  public:
828  explicit LBranch(LOperand* value, LOperand *temp1, LOperand *temp2) {
829  inputs_[0] = value;
830  temps_[0] = temp1;
831  temps_[1] = temp2;
832  }
833 
834  LOperand* value() { return inputs_[0]; }
835  LOperand* temp1() { return temps_[0]; }
836  LOperand* temp2() { return temps_[1]; }
837 
838  DECLARE_CONCRETE_INSTRUCTION(Branch, "branch")
840 
841  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
842 };
843 
844 
845 class LCallJSFunction FINAL : public LTemplateInstruction<1, 1, 0> {
846  public:
847  explicit LCallJSFunction(LOperand* function) {
848  inputs_[0] = function;
849  }
850 
851  LOperand* function() { return inputs_[0]; }
852 
853  DECLARE_CONCRETE_INSTRUCTION(CallJSFunction, "call-js-function")
854  DECLARE_HYDROGEN_ACCESSOR(CallJSFunction)
855 
856  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
857 
858  int arity() const { return hydrogen()->argument_count() - 1; }
859 };
860 
861 
862 class LCallFunction FINAL : public LTemplateInstruction<1, 2, 0> {
863  public:
864  LCallFunction(LOperand* context, LOperand* function) {
865  inputs_[0] = context;
866  inputs_[1] = function;
867  }
868 
869  LOperand* context() { return inputs_[0]; }
870  LOperand* function() { return inputs_[1]; }
871 
872  DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call-function")
873  DECLARE_HYDROGEN_ACCESSOR(CallFunction)
874 
875  int arity() const { return hydrogen()->argument_count() - 1; }
876 };
877 
878 
879 class LCallNew FINAL : public LTemplateInstruction<1, 2, 0> {
880  public:
881  LCallNew(LOperand* context, LOperand* constructor) {
882  inputs_[0] = context;
883  inputs_[1] = constructor;
884  }
885 
886  LOperand* context() { return inputs_[0]; }
887  LOperand* constructor() { return inputs_[1]; }
888 
889  DECLARE_CONCRETE_INSTRUCTION(CallNew, "call-new")
891 
892  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
893 
894  int arity() const { return hydrogen()->argument_count() - 1; }
895 };
896 
897 
898 class LCallNewArray FINAL : public LTemplateInstruction<1, 2, 0> {
899  public:
900  LCallNewArray(LOperand* context, LOperand* constructor) {
901  inputs_[0] = context;
902  inputs_[1] = constructor;
903  }
904 
905  LOperand* context() { return inputs_[0]; }
906  LOperand* constructor() { return inputs_[1]; }
907 
908  DECLARE_CONCRETE_INSTRUCTION(CallNewArray, "call-new-array")
909  DECLARE_HYDROGEN_ACCESSOR(CallNewArray)
910 
911  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
912 
913  int arity() const { return hydrogen()->argument_count() - 1; }
914 };
915 
916 
917 class LCallRuntime FINAL : public LTemplateInstruction<1, 1, 0> {
918  public:
919  explicit LCallRuntime(LOperand* context) {
920  inputs_[0] = context;
921  }
922 
923  LOperand* context() { return inputs_[0]; }
924 
925  DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime")
926  DECLARE_HYDROGEN_ACCESSOR(CallRuntime)
927 
928  virtual bool ClobbersDoubleRegisters(Isolate* isolate) const OVERRIDE {
929  return save_doubles() == kDontSaveFPRegs;
930  }
931 
932  const Runtime::Function* function() const { return hydrogen()->function(); }
933  int arity() const { return hydrogen()->argument_count(); }
934  SaveFPRegsMode save_doubles() const { return hydrogen()->save_doubles(); }
935 };
936 
937 
938 class LCallStub FINAL : public LTemplateInstruction<1, 1, 0> {
939  public:
940  explicit LCallStub(LOperand* context) {
941  inputs_[0] = context;
942  }
943 
944  LOperand* context() { return inputs_[0]; }
945 
946  DECLARE_CONCRETE_INSTRUCTION(CallStub, "call-stub")
947  DECLARE_HYDROGEN_ACCESSOR(CallStub)
948 };
949 
950 
951 class LCheckInstanceType FINAL : public LTemplateInstruction<0, 1, 1> {
952  public:
953  explicit LCheckInstanceType(LOperand* value, LOperand* temp) {
954  inputs_[0] = value;
955  temps_[0] = temp;
956  }
957 
958  LOperand* value() { return inputs_[0]; }
959  LOperand* temp() { return temps_[0]; }
960 
961  DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check-instance-type")
962  DECLARE_HYDROGEN_ACCESSOR(CheckInstanceType)
963 };
964 
965 
966 class LCheckMaps FINAL : public LTemplateInstruction<0, 1, 1> {
967  public:
968  explicit LCheckMaps(LOperand* value = NULL, LOperand* temp = NULL) {
969  inputs_[0] = value;
970  temps_[0] = temp;
971  }
972 
973  LOperand* value() { return inputs_[0]; }
974  LOperand* temp() { return temps_[0]; }
975 
976  DECLARE_CONCRETE_INSTRUCTION(CheckMaps, "check-maps")
977  DECLARE_HYDROGEN_ACCESSOR(CheckMaps)
978 };
979 
980 
981 class LCheckNonSmi FINAL : public LTemplateInstruction<0, 1, 0> {
982  public:
983  explicit LCheckNonSmi(LOperand* value) {
984  inputs_[0] = value;
985  }
986 
987  LOperand* value() { return inputs_[0]; }
988 
989  DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check-non-smi")
990  DECLARE_HYDROGEN_ACCESSOR(CheckHeapObject)
991 };
992 
993 
994 class LCheckSmi FINAL : public LTemplateInstruction<1, 1, 0> {
995  public:
996  explicit LCheckSmi(LOperand* value) {
997  inputs_[0] = value;
998  }
999 
1000  LOperand* value() { return inputs_[0]; }
1001 
1002  DECLARE_CONCRETE_INSTRUCTION(CheckSmi, "check-smi")
1003 };
1004 
1005 
1006 class LCheckValue FINAL : public LTemplateInstruction<0, 1, 0> {
1007  public:
1008  explicit LCheckValue(LOperand* value) {
1009  inputs_[0] = value;
1010  }
1011 
1012  LOperand* value() { return inputs_[0]; }
1013 
1014  DECLARE_CONCRETE_INSTRUCTION(CheckValue, "check-value")
1015  DECLARE_HYDROGEN_ACCESSOR(CheckValue)
1016 };
1017 
1018 
1019 class LClampDToUint8 FINAL : public LTemplateInstruction<1, 1, 0> {
1020  public:
1021  explicit LClampDToUint8(LOperand* unclamped) {
1022  inputs_[0] = unclamped;
1023  }
1024 
1025  LOperand* unclamped() { return inputs_[0]; }
1026 
1027  DECLARE_CONCRETE_INSTRUCTION(ClampDToUint8, "clamp-d-to-uint8")
1028 };
1029 
1030 
1031 class LClampIToUint8 FINAL : public LTemplateInstruction<1, 1, 0> {
1032  public:
1033  explicit LClampIToUint8(LOperand* unclamped) {
1034  inputs_[0] = unclamped;
1035  }
1036 
1037  LOperand* unclamped() { return inputs_[0]; }
1038 
1039  DECLARE_CONCRETE_INSTRUCTION(ClampIToUint8, "clamp-i-to-uint8")
1040 };
1041 
1042 
1043 class LClampTToUint8 FINAL : public LTemplateInstruction<1, 1, 1> {
1044  public:
1045  LClampTToUint8(LOperand* unclamped, LOperand* temp1) {
1046  inputs_[0] = unclamped;
1047  temps_[0] = temp1;
1048  }
1049 
1050  LOperand* unclamped() { return inputs_[0]; }
1051  LOperand* temp1() { return temps_[0]; }
1052 
1053  DECLARE_CONCRETE_INSTRUCTION(ClampTToUint8, "clamp-t-to-uint8")
1054 };
1055 
1056 
1057 class LDoubleBits FINAL : public LTemplateInstruction<1, 1, 0> {
1058  public:
1059  explicit LDoubleBits(LOperand* value) {
1060  inputs_[0] = value;
1061  }
1062 
1063  LOperand* value() { return inputs_[0]; }
1064 
1065  DECLARE_CONCRETE_INSTRUCTION(DoubleBits, "double-bits")
1066  DECLARE_HYDROGEN_ACCESSOR(DoubleBits)
1067 };
1068 
1069 
1070 class LConstructDouble FINAL : public LTemplateInstruction<1, 2, 0> {
1071  public:
1073  inputs_[0] = hi;
1074  inputs_[1] = lo;
1075  }
1076 
1077  LOperand* hi() { return inputs_[0]; }
1078  LOperand* lo() { return inputs_[1]; }
1079 
1080  DECLARE_CONCRETE_INSTRUCTION(ConstructDouble, "construct-double")
1081 };
1082 
1083 
1084 class LClassOfTestAndBranch FINAL : public LControlInstruction<1, 2> {
1085  public:
1087  inputs_[0] = value;
1088  temps_[0] = temp1;
1089  temps_[1] = temp2;
1090  }
1091 
1092  LOperand* value() { return inputs_[0]; }
1093  LOperand* temp1() { return temps_[0]; }
1094  LOperand* temp2() { return temps_[1]; }
1095 
1096  DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch,
1097  "class-of-test-and-branch")
1098  DECLARE_HYDROGEN_ACCESSOR(ClassOfTestAndBranch)
1099 
1100  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1101 };
1102 
1103 
1104 class LCmpHoleAndBranchD FINAL : public LControlInstruction<1, 1> {
1105  public:
1106  explicit LCmpHoleAndBranchD(LOperand* object, LOperand* temp) {
1107  inputs_[0] = object;
1108  temps_[0] = temp;
1109  }
1110 
1111  LOperand* object() { return inputs_[0]; }
1112  LOperand* temp() { return temps_[0]; }
1113 
1114  DECLARE_CONCRETE_INSTRUCTION(CmpHoleAndBranchD, "cmp-hole-and-branch-d")
1115  DECLARE_HYDROGEN_ACCESSOR(CompareHoleAndBranch)
1116 };
1117 
1118 
1119 class LCmpHoleAndBranchT FINAL : public LControlInstruction<1, 0> {
1120  public:
1121  explicit LCmpHoleAndBranchT(LOperand* object) {
1122  inputs_[0] = object;
1123  }
1124 
1125  LOperand* object() { return inputs_[0]; }
1126 
1127  DECLARE_CONCRETE_INSTRUCTION(CmpHoleAndBranchT, "cmp-hole-and-branch-t")
1128  DECLARE_HYDROGEN_ACCESSOR(CompareHoleAndBranch)
1129 };
1130 
1131 
1132 class LCmpMapAndBranch FINAL : public LControlInstruction<1, 1> {
1133  public:
1135  inputs_[0] = value;
1136  temps_[0] = temp;
1137  }
1138 
1139  LOperand* value() { return inputs_[0]; }
1140  LOperand* temp() { return temps_[0]; }
1141 
1142  DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch")
1143  DECLARE_HYDROGEN_ACCESSOR(CompareMap)
1144 
1145  Handle<Map> map() const { return hydrogen()->map().handle(); }
1146 };
1147 
1148 
1149 class LCmpObjectEqAndBranch FINAL : public LControlInstruction<2, 0> {
1150  public:
1152  inputs_[0] = left;
1153  inputs_[1] = right;
1154  }
1155 
1156  LOperand* left() { return inputs_[0]; }
1157  LOperand* right() { return inputs_[1]; }
1158 
1159  DECLARE_CONCRETE_INSTRUCTION(CmpObjectEqAndBranch, "cmp-object-eq-and-branch")
1160  DECLARE_HYDROGEN_ACCESSOR(CompareObjectEqAndBranch)
1161 };
1162 
1163 
1164 class LCmpT FINAL : public LTemplateInstruction<1, 3, 0> {
1165  public:
1166  LCmpT(LOperand* context, LOperand* left, LOperand* right) {
1167  inputs_[0] = context;
1168  inputs_[1] = left;
1169  inputs_[2] = right;
1170  }
1171 
1172  LOperand* context() { return inputs_[0]; }
1173  LOperand* left() { return inputs_[1]; }
1174  LOperand* right() { return inputs_[2]; }
1175 
1176  DECLARE_CONCRETE_INSTRUCTION(CmpT, "cmp-t")
1177  DECLARE_HYDROGEN_ACCESSOR(CompareGeneric)
1178 
1179  Token::Value op() const { return hydrogen()->token(); }
1180 };
1181 
1182 
1183 class LCompareMinusZeroAndBranch FINAL : public LControlInstruction<1, 1> {
1184  public:
1186  inputs_[0] = value;
1187  temps_[0] = temp;
1188  }
1189 
1190  LOperand* value() { return inputs_[0]; }
1191  LOperand* temp() { return temps_[0]; }
1192 
1193  DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch,
1194  "cmp-minus-zero-and-branch")
1195  DECLARE_HYDROGEN_ACCESSOR(CompareMinusZeroAndBranch)
1196 };
1197 
1198 
1199 class LCompareNumericAndBranch FINAL : public LControlInstruction<2, 0> {
1200  public:
1202  inputs_[0] = left;
1203  inputs_[1] = right;
1204  }
1205 
1206  LOperand* left() { return inputs_[0]; }
1207  LOperand* right() { return inputs_[1]; }
1208 
1209  DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch,
1210  "compare-numeric-and-branch")
1211  DECLARE_HYDROGEN_ACCESSOR(CompareNumericAndBranch)
1212 
1213  Token::Value op() const { return hydrogen()->token(); }
1214  bool is_double() const {
1215  return hydrogen()->representation().IsDouble();
1216  }
1217 
1218  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1219 };
1220 
1221 
1222 class LConstantD FINAL : public LTemplateInstruction<1, 0, 0> {
1223  public:
1224  DECLARE_CONCRETE_INSTRUCTION(ConstantD, "constant-d")
1225  DECLARE_HYDROGEN_ACCESSOR(Constant)
1226 
1227  double value() const { return hydrogen()->DoubleValue(); }
1228 };
1229 
1230 
1231 class LConstantE FINAL : public LTemplateInstruction<1, 0, 0> {
1232  public:
1233  DECLARE_CONCRETE_INSTRUCTION(ConstantE, "constant-e")
1234  DECLARE_HYDROGEN_ACCESSOR(Constant)
1235 
1236  ExternalReference value() const {
1237  return hydrogen()->ExternalReferenceValue();
1238  }
1239 };
1240 
1241 
1242 class LConstantI FINAL : public LTemplateInstruction<1, 0, 0> {
1243  public:
1244  DECLARE_CONCRETE_INSTRUCTION(ConstantI, "constant-i")
1245  DECLARE_HYDROGEN_ACCESSOR(Constant)
1246 
1247  int32_t value() const { return hydrogen()->Integer32Value(); }
1248 };
1249 
1250 
1251 class LConstantS FINAL : public LTemplateInstruction<1, 0, 0> {
1252  public:
1253  DECLARE_CONCRETE_INSTRUCTION(ConstantS, "constant-s")
1254  DECLARE_HYDROGEN_ACCESSOR(Constant)
1255 
1256  Smi* value() const { return Smi::FromInt(hydrogen()->Integer32Value()); }
1257 };
1258 
1259 
1260 class LConstantT FINAL : public LTemplateInstruction<1, 0, 0> {
1261  public:
1262  DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t")
1263  DECLARE_HYDROGEN_ACCESSOR(Constant)
1264 
1265  Handle<Object> value(Isolate* isolate) const {
1266  return hydrogen()->handle(isolate);
1267  }
1268 };
1269 
1270 
1271 class LContext FINAL : public LTemplateInstruction<1, 0, 0> {
1272  public:
1275 };
1276 
1277 
1278 class LDateField FINAL : public LTemplateInstruction<1, 1, 0> {
1279  public:
1280  LDateField(LOperand* date, Smi* index) : index_(index) {
1281  inputs_[0] = date;
1282  }
1283 
1284  LOperand* date() { return inputs_[0]; }
1285  Smi* index() const { return index_; }
1286 
1287  DECLARE_CONCRETE_INSTRUCTION(DateField, "date-field")
1288  DECLARE_HYDROGEN_ACCESSOR(DateField)
1289 
1290  private:
1291  Smi* index_;
1292 };
1293 
1294 
1295 class LDebugBreak FINAL : public LTemplateInstruction<0, 0, 0> {
1296  public:
1297  DECLARE_CONCRETE_INSTRUCTION(DebugBreak, "break")
1298 };
1299 
1300 
1301 class LDeclareGlobals FINAL : public LTemplateInstruction<0, 1, 0> {
1302  public:
1303  explicit LDeclareGlobals(LOperand* context) {
1304  inputs_[0] = context;
1305  }
1306 
1307  LOperand* context() { return inputs_[0]; }
1308 
1309  DECLARE_CONCRETE_INSTRUCTION(DeclareGlobals, "declare-globals")
1311 };
1312 
1313 
1314 class LDeoptimize FINAL : public LTemplateInstruction<0, 0, 0> {
1315  public:
1316  virtual bool IsControl() const OVERRIDE { return true; }
1317  DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
1318  DECLARE_HYDROGEN_ACCESSOR(Deoptimize)
1319 };
1320 
1321 
1322 class LDivByPowerOf2I FINAL : public LTemplateInstruction<1, 1, 0> {
1323  public:
1324  LDivByPowerOf2I(LOperand* dividend, int32_t divisor) {
1325  inputs_[0] = dividend;
1326  divisor_ = divisor;
1327  }
1328 
1329  LOperand* dividend() { return inputs_[0]; }
1330  int32_t divisor() const { return divisor_; }
1331 
1332  DECLARE_CONCRETE_INSTRUCTION(DivByPowerOf2I, "div-by-power-of-2-i")
1334 
1335  private:
1336  int32_t divisor_;
1337 };
1338 
1339 
1340 class LDivByConstI FINAL : public LTemplateInstruction<1, 1, 1> {
1341  public:
1342  LDivByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) {
1343  inputs_[0] = dividend;
1344  divisor_ = divisor;
1345  temps_[0] = temp;
1346  }
1347 
1348  LOperand* dividend() { return inputs_[0]; }
1349  int32_t divisor() const { return divisor_; }
1350  LOperand* temp() { return temps_[0]; }
1351 
1352  DECLARE_CONCRETE_INSTRUCTION(DivByConstI, "div-by-const-i")
1354 
1355  private:
1356  int32_t divisor_;
1357 };
1358 
1359 
1360 class LDivI FINAL : public LTemplateInstruction<1, 2, 1> {
1361  public:
1362  LDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) {
1363  inputs_[0] = dividend;
1364  inputs_[1] = divisor;
1365  temps_[0] = temp;
1366  }
1367 
1368  LOperand* dividend() { return inputs_[0]; }
1369  LOperand* divisor() { return inputs_[1]; }
1370  LOperand* temp() { return temps_[0]; }
1371 
1372  DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
1373  DECLARE_HYDROGEN_ACCESSOR(BinaryOperation)
1374 };
1375 
1376 
1377 class LDoubleToIntOrSmi FINAL : public LTemplateInstruction<1, 1, 0> {
1378  public:
1379  explicit LDoubleToIntOrSmi(LOperand* value) {
1380  inputs_[0] = value;
1381  }
1382 
1383  LOperand* value() { return inputs_[0]; }
1384 
1385  DECLARE_CONCRETE_INSTRUCTION(DoubleToIntOrSmi, "double-to-int-or-smi")
1386  DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
1387 
1388  bool tag_result() { return hydrogen()->representation().IsSmi(); }
1389 };
1390 
1391 
1392 class LForInCacheArray FINAL : public LTemplateInstruction<1, 1, 0> {
1393  public:
1395  inputs_[0] = map;
1396  }
1397 
1398  LOperand* map() { return inputs_[0]; }
1399 
1400  DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray, "for-in-cache-array")
1401 
1402  int idx() {
1403  return HForInCacheArray::cast(this->hydrogen_value())->idx();
1404  }
1405 };
1406 
1407 
1408 class LForInPrepareMap FINAL : public LTemplateInstruction<1, 2, 0> {
1409  public:
1410  LForInPrepareMap(LOperand* context, LOperand* object) {
1411  inputs_[0] = context;
1412  inputs_[1] = object;
1413  }
1414 
1415  LOperand* context() { return inputs_[0]; }
1416  LOperand* object() { return inputs_[1]; }
1417 
1418  DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap, "for-in-prepare-map")
1419 };
1420 
1421 
1422 class LGetCachedArrayIndex FINAL : public LTemplateInstruction<1, 1, 0> {
1423  public:
1424  explicit LGetCachedArrayIndex(LOperand* value) {
1425  inputs_[0] = value;
1426  }
1427 
1428  LOperand* value() { return inputs_[0]; }
1429 
1430  DECLARE_CONCRETE_INSTRUCTION(GetCachedArrayIndex, "get-cached-array-index")
1431  DECLARE_HYDROGEN_ACCESSOR(GetCachedArrayIndex)
1432 };
1433 
1434 
1435 class LHasCachedArrayIndexAndBranch FINAL
1436  : public LControlInstruction<1, 1> {
1437  public:
1439  inputs_[0] = value;
1440  temps_[0] = temp;
1441  }
1442 
1443  LOperand* value() { return inputs_[0]; }
1444  LOperand* temp() { return temps_[0]; }
1445 
1446  DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch,
1447  "has-cached-array-index-and-branch")
1448  DECLARE_HYDROGEN_ACCESSOR(HasCachedArrayIndexAndBranch)
1449 
1450  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1451 };
1452 
1453 
1454 class LHasInstanceTypeAndBranch FINAL : public LControlInstruction<1, 1> {
1455  public:
1457  inputs_[0] = value;
1458  temps_[0] = temp;
1459  }
1460 
1461  LOperand* value() { return inputs_[0]; }
1462  LOperand* temp() { return temps_[0]; }
1463 
1464  DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch,
1465  "has-instance-type-and-branch")
1466  DECLARE_HYDROGEN_ACCESSOR(HasInstanceTypeAndBranch)
1467 
1468  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1469 };
1470 
1471 
1472 class LInnerAllocatedObject FINAL : public LTemplateInstruction<1, 2, 0> {
1473  public:
1474  LInnerAllocatedObject(LOperand* base_object, LOperand* offset) {
1475  inputs_[0] = base_object;
1476  inputs_[1] = offset;
1477  }
1478 
1479  LOperand* base_object() const { return inputs_[0]; }
1480  LOperand* offset() const { return inputs_[1]; }
1481 
1482  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1483 
1484  DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject, "inner-allocated-object")
1485 };
1486 
1487 
1488 class LInstanceOf FINAL : public LTemplateInstruction<1, 3, 0> {
1489  public:
1490  LInstanceOf(LOperand* context, LOperand* left, LOperand* right) {
1491  inputs_[0] = context;
1492  inputs_[1] = left;
1493  inputs_[2] = right;
1494  }
1495 
1496  LOperand* context() { return inputs_[0]; }
1497  LOperand* left() { return inputs_[1]; }
1498  LOperand* right() { return inputs_[2]; }
1499 
1500  DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of")
1501 };
1502 
1503 
1504 class LInstanceOfKnownGlobal FINAL : public LTemplateInstruction<1, 2, 0> {
1505  public:
1507  inputs_[0] = context;
1508  inputs_[1] = value;
1509  }
1510 
1511  LOperand* context() { return inputs_[0]; }
1512  LOperand* value() { return inputs_[1]; }
1513 
1514  DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal,
1515  "instance-of-known-global")
1516  DECLARE_HYDROGEN_ACCESSOR(InstanceOfKnownGlobal)
1517 
1518  Handle<JSFunction> function() const { return hydrogen()->function(); }
1520  return lazy_deopt_env_;
1521  }
1523  LEnvironment* env) OVERRIDE {
1524  lazy_deopt_env_ = env;
1525  }
1526 
1527  private:
1528  LEnvironment* lazy_deopt_env_;
1529 };
1530 
1531 
1532 class LInteger32ToDouble FINAL : public LTemplateInstruction<1, 1, 0> {
1533  public:
1534  explicit LInteger32ToDouble(LOperand* value) {
1535  inputs_[0] = value;
1536  }
1537 
1538  LOperand* value() { return inputs_[0]; }
1539 
1540  DECLARE_CONCRETE_INSTRUCTION(Integer32ToDouble, "int32-to-double")
1541 };
1542 
1543 
1544 class LCallWithDescriptor FINAL : public LTemplateResultInstruction<1> {
1545  public:
1547  const ZoneList<LOperand*>& operands, Zone* zone)
1548  : descriptor_(descriptor),
1549  inputs_(descriptor.GetRegisterParameterCount() + 1, zone) {
1550  DCHECK(descriptor.GetRegisterParameterCount() + 1 == operands.length());
1551  inputs_.AddAll(operands, zone);
1552  }
1553 
1554  LOperand* target() const { return inputs_[0]; }
1555 
1556  CallInterfaceDescriptor descriptor() { return descriptor_; }
1557 
1558  private:
1559  DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor, "call-with-descriptor")
1560  DECLARE_HYDROGEN_ACCESSOR(CallWithDescriptor)
1561 
1562  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1563 
1564  int arity() const { return hydrogen()->argument_count() - 1; }
1565 
1566  CallInterfaceDescriptor descriptor_;
1567  ZoneList<LOperand*> inputs_;
1568 
1569  // Iterator support.
1570  virtual int InputCount() FINAL OVERRIDE { return inputs_.length(); }
1571  virtual LOperand* InputAt(int i) FINAL OVERRIDE { return inputs_[i]; }
1572 
1573  virtual int TempCount() FINAL OVERRIDE { return 0; }
1574  virtual LOperand* TempAt(int i) FINAL OVERRIDE { return NULL; }
1575 };
1576 
1577 
1578 class LInvokeFunction FINAL : public LTemplateInstruction<1, 2, 0> {
1579  public:
1580  LInvokeFunction(LOperand* context, LOperand* function) {
1581  inputs_[0] = context;
1582  inputs_[1] = function;
1583  }
1584 
1585  LOperand* context() { return inputs_[0]; }
1586  LOperand* function() { return inputs_[1]; }
1587 
1588  DECLARE_CONCRETE_INSTRUCTION(InvokeFunction, "invoke-function")
1589  DECLARE_HYDROGEN_ACCESSOR(InvokeFunction)
1590 
1591  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1592 
1593  int arity() const { return hydrogen()->argument_count() - 1; }
1594 };
1595 
1596 
1597 class LIsConstructCallAndBranch FINAL : public LControlInstruction<0, 2> {
1598  public:
1600  temps_[0] = temp1;
1601  temps_[1] = temp2;
1602  }
1603 
1604  LOperand* temp1() { return temps_[0]; }
1605  LOperand* temp2() { return temps_[1]; }
1606 
1607  DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch,
1608  "is-construct-call-and-branch")
1609 };
1610 
1611 
1612 class LIsObjectAndBranch FINAL : public LControlInstruction<1, 2> {
1613  public:
1614  LIsObjectAndBranch(LOperand* value, LOperand* temp1, LOperand* temp2) {
1615  inputs_[0] = value;
1616  temps_[0] = temp1;
1617  temps_[1] = temp2;
1618  }
1619 
1620  LOperand* value() { return inputs_[0]; }
1621  LOperand* temp1() { return temps_[0]; }
1622  LOperand* temp2() { return temps_[1]; }
1623 
1624  DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch, "is-object-and-branch")
1625  DECLARE_HYDROGEN_ACCESSOR(IsObjectAndBranch)
1626 
1627  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1628 };
1629 
1630 
1631 class LIsStringAndBranch FINAL : public LControlInstruction<1, 1> {
1632  public:
1634  inputs_[0] = value;
1635  temps_[0] = temp;
1636  }
1637 
1638  LOperand* value() { return inputs_[0]; }
1639  LOperand* temp() { return temps_[0]; }
1640 
1641  DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch, "is-string-and-branch")
1642  DECLARE_HYDROGEN_ACCESSOR(IsStringAndBranch)
1643 
1644  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1645 };
1646 
1647 
1648 class LIsSmiAndBranch FINAL : public LControlInstruction<1, 0> {
1649  public:
1650  explicit LIsSmiAndBranch(LOperand* value) {
1651  inputs_[0] = value;
1652  }
1653 
1654  LOperand* value() { return inputs_[0]; }
1655 
1656  DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch, "is-smi-and-branch")
1657  DECLARE_HYDROGEN_ACCESSOR(IsSmiAndBranch)
1658 
1659  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1660 };
1661 
1662 
1663 class LIsUndetectableAndBranch FINAL : public LControlInstruction<1, 1> {
1664  public:
1665  explicit LIsUndetectableAndBranch(LOperand* value, LOperand* temp) {
1666  inputs_[0] = value;
1667  temps_[0] = temp;
1668  }
1669 
1670  LOperand* value() { return inputs_[0]; }
1671  LOperand* temp() { return temps_[0]; }
1672 
1673  DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch,
1674  "is-undetectable-and-branch")
1675  DECLARE_HYDROGEN_ACCESSOR(IsUndetectableAndBranch)
1676 
1677  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1678 };
1679 
1680 
1681 class LLoadContextSlot FINAL : public LTemplateInstruction<1, 1, 0> {
1682  public:
1683  explicit LLoadContextSlot(LOperand* context) {
1684  inputs_[0] = context;
1685  }
1686 
1687  LOperand* context() { return inputs_[0]; }
1688 
1689  DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load-context-slot")
1690  DECLARE_HYDROGEN_ACCESSOR(LoadContextSlot)
1691 
1692  int slot_index() const { return hydrogen()->slot_index(); }
1693 
1694  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
1695 };
1696 
1697 
1698 class LLoadNamedField FINAL : public LTemplateInstruction<1, 1, 0> {
1699  public:
1700  explicit LLoadNamedField(LOperand* object) {
1701  inputs_[0] = object;
1702  }
1703 
1704  LOperand* object() { return inputs_[0]; }
1705 
1706  DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field")
1707  DECLARE_HYDROGEN_ACCESSOR(LoadNamedField)
1708 };
1709 
1710 
1711 class LFunctionLiteral FINAL : public LTemplateInstruction<1, 1, 0> {
1712  public:
1713  explicit LFunctionLiteral(LOperand* context) {
1714  inputs_[0] = context;
1715  }
1716 
1717  LOperand* context() { return inputs_[0]; }
1718 
1719  DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function-literal")
1720  DECLARE_HYDROGEN_ACCESSOR(FunctionLiteral)
1721 };
1722 
1723 
1724 class LLoadFunctionPrototype FINAL : public LTemplateInstruction<1, 1, 1> {
1725  public:
1727  inputs_[0] = function;
1728  temps_[0] = temp;
1729  }
1730 
1731  LOperand* function() { return inputs_[0]; }
1732  LOperand* temp() { return temps_[0]; }
1733 
1734  DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype")
1735  DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype)
1736 };
1737 
1738 
1739 class LLoadGlobalCell FINAL : public LTemplateInstruction<1, 0, 0> {
1740  public:
1741  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalCell, "load-global-cell")
1742  DECLARE_HYDROGEN_ACCESSOR(LoadGlobalCell)
1743 };
1744 
1745 
1746 class LLoadGlobalGeneric FINAL : public LTemplateInstruction<1, 2, 1> {
1747  public:
1748  LLoadGlobalGeneric(LOperand* context, LOperand* global_object,
1749  LOperand* vector) {
1750  inputs_[0] = context;
1751  inputs_[1] = global_object;
1752  temps_[0] = vector;
1753  }
1754 
1755  LOperand* context() { return inputs_[0]; }
1756  LOperand* global_object() { return inputs_[1]; }
1757  LOperand* temp_vector() { return temps_[0]; }
1758 
1759  DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
1760  DECLARE_HYDROGEN_ACCESSOR(LoadGlobalGeneric)
1761 
1762  Handle<Object> name() const { return hydrogen()->name(); }
1763  bool for_typeof() const { return hydrogen()->for_typeof(); }
1764 };
1765 
1766 
1767 template<int T>
1768 class LLoadKeyed : public LTemplateInstruction<1, 2, T> {
1769  public:
1770  LLoadKeyed(LOperand* elements, LOperand* key) {
1771  this->inputs_[0] = elements;
1772  this->inputs_[1] = key;
1773  }
1774 
1775  LOperand* elements() { return this->inputs_[0]; }
1776  LOperand* key() { return this->inputs_[1]; }
1778  return this->hydrogen()->elements_kind();
1779  }
1780  bool is_external() const {
1781  return this->hydrogen()->is_external();
1782  }
1783  bool is_fixed_typed_array() const {
1784  return hydrogen()->is_fixed_typed_array();
1785  }
1786  bool is_typed_elements() const {
1787  return is_external() || is_fixed_typed_array();
1788  }
1790  return this->hydrogen()->base_offset();
1791  }
1792  void PrintDataTo(StringStream* stream) OVERRIDE {
1793  this->elements()->PrintTo(stream);
1794  stream->Add("[");
1795  this->key()->PrintTo(stream);
1796  if (this->base_offset() != 0) {
1797  stream->Add(" + %d]", this->base_offset());
1798  } else {
1799  stream->Add("]");
1800  }
1801  }
1802 
1803  DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
1804 };
1805 
1806 
1807 class LLoadKeyedExternal: public LLoadKeyed<1> {
1808  public:
1809  LLoadKeyedExternal(LOperand* elements, LOperand* key, LOperand* temp) :
1810  LLoadKeyed<1>(elements, key) {
1811  temps_[0] = temp;
1812  }
1813 
1814  LOperand* temp() { return temps_[0]; }
1815 
1816  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedExternal, "load-keyed-external");
1817 };
1818 
1819 
1820 class LLoadKeyedFixed: public LLoadKeyed<1> {
1821  public:
1822  LLoadKeyedFixed(LOperand* elements, LOperand* key, LOperand* temp) :
1823  LLoadKeyed<1>(elements, key) {
1824  temps_[0] = temp;
1825  }
1826 
1827  LOperand* temp() { return temps_[0]; }
1828 
1829  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFixed, "load-keyed-fixed");
1830 };
1831 
1832 
1834  public:
1836  LLoadKeyed<1>(elements, key) {
1837  temps_[0] = temp;
1838  }
1839 
1840  LOperand* temp() { return temps_[0]; }
1841 
1842  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFixedDouble, "load-keyed-fixed-double");
1843 };
1844 
1845 
1846 class LLoadKeyedGeneric FINAL : public LTemplateInstruction<1, 3, 1> {
1847  public:
1848  LLoadKeyedGeneric(LOperand* context, LOperand* object, LOperand* key,
1849  LOperand* vector) {
1850  inputs_[0] = context;
1851  inputs_[1] = object;
1852  inputs_[2] = key;
1853  temps_[0] = vector;
1854  }
1855 
1856  LOperand* context() { return inputs_[0]; }
1857  LOperand* object() { return inputs_[1]; }
1858  LOperand* key() { return inputs_[2]; }
1859  LOperand* temp_vector() { return temps_[0]; }
1860 
1861  DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load-keyed-generic")
1862  DECLARE_HYDROGEN_ACCESSOR(LoadKeyedGeneric)
1863 };
1864 
1865 
1866 class LLoadNamedGeneric FINAL : public LTemplateInstruction<1, 2, 1> {
1867  public:
1868  LLoadNamedGeneric(LOperand* context, LOperand* object, LOperand* vector) {
1869  inputs_[0] = context;
1870  inputs_[1] = object;
1871  temps_[0] = vector;
1872  }
1873 
1874  LOperand* context() { return inputs_[0]; }
1875  LOperand* object() { return inputs_[1]; }
1876  LOperand* temp_vector() { return temps_[0]; }
1877 
1878  DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load-named-generic")
1879  DECLARE_HYDROGEN_ACCESSOR(LoadNamedGeneric)
1880 
1881  Handle<Object> name() const { return hydrogen()->name(); }
1882 };
1883 
1884 
1885 class LLoadRoot FINAL : public LTemplateInstruction<1, 0, 0> {
1886  public:
1887  DECLARE_CONCRETE_INSTRUCTION(LoadRoot, "load-root")
1888  DECLARE_HYDROGEN_ACCESSOR(LoadRoot)
1889 
1890  Heap::RootListIndex index() const { return hydrogen()->index(); }
1891 };
1892 
1893 
1894 class LMapEnumLength FINAL : public LTemplateInstruction<1, 1, 0> {
1895  public:
1896  explicit LMapEnumLength(LOperand* value) {
1897  inputs_[0] = value;
1898  }
1899 
1900  LOperand* value() { return inputs_[0]; }
1901 
1902  DECLARE_CONCRETE_INSTRUCTION(MapEnumLength, "map-enum-length")
1903 };
1904 
1905 
1906 template<int T>
1908  public:
1909  explicit LUnaryMathOperation(LOperand* value) {
1910  this->inputs_[0] = value;
1911  }
1912 
1913  LOperand* value() { return this->inputs_[0]; }
1914  BuiltinFunctionId op() const { return this->hydrogen()->op(); }
1915 
1916  void PrintDataTo(StringStream* stream) OVERRIDE;
1917 
1918  DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
1919 };
1920 
1921 
1922 class LMathAbs FINAL : public LUnaryMathOperation<0> {
1923  public:
1924  explicit LMathAbs(LOperand* value) : LUnaryMathOperation<0>(value) {}
1925 
1926  DECLARE_CONCRETE_INSTRUCTION(MathAbs, "math-abs")
1927 };
1928 
1929 
1930 class LMathAbsTagged: public LTemplateInstruction<1, 2, 3> {
1931  public:
1933  LOperand* temp1, LOperand* temp2, LOperand* temp3) {
1934  inputs_[0] = context;
1935  inputs_[1] = value;
1936  temps_[0] = temp1;
1937  temps_[1] = temp2;
1938  temps_[2] = temp3;
1939  }
1940 
1941  LOperand* context() { return inputs_[0]; }
1942  LOperand* value() { return inputs_[1]; }
1943  LOperand* temp1() { return temps_[0]; }
1944  LOperand* temp2() { return temps_[1]; }
1945  LOperand* temp3() { return temps_[2]; }
1946 
1947  DECLARE_CONCRETE_INSTRUCTION(MathAbsTagged, "math-abs-tagged")
1948  DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
1949 };
1950 
1951 
1952 class LMathExp FINAL : public LUnaryMathOperation<4> {
1953  public:
1955  LOperand* double_temp1,
1956  LOperand* temp1,
1957  LOperand* temp2,
1958  LOperand* temp3)
1959  : LUnaryMathOperation<4>(value) {
1960  temps_[0] = double_temp1;
1961  temps_[1] = temp1;
1962  temps_[2] = temp2;
1963  temps_[3] = temp3;
1964  ExternalReference::InitializeMathExpData();
1965  }
1966 
1967  LOperand* double_temp1() { return temps_[0]; }
1968  LOperand* temp1() { return temps_[1]; }
1969  LOperand* temp2() { return temps_[2]; }
1970  LOperand* temp3() { return temps_[3]; }
1971 
1972  DECLARE_CONCRETE_INSTRUCTION(MathExp, "math-exp")
1973 };
1974 
1975 
1976 // Math.floor with a double result.
1977 class LMathFloorD FINAL : public LUnaryMathOperation<0> {
1978  public:
1979  explicit LMathFloorD(LOperand* value) : LUnaryMathOperation<0>(value) { }
1980  DECLARE_CONCRETE_INSTRUCTION(MathFloorD, "math-floor-d")
1981 };
1982 
1983 
1984 // Math.floor with an integer result.
1985 class LMathFloorI FINAL : public LUnaryMathOperation<0> {
1986  public:
1987  explicit LMathFloorI(LOperand* value) : LUnaryMathOperation<0>(value) { }
1988  DECLARE_CONCRETE_INSTRUCTION(MathFloorI, "math-floor-i")
1989 };
1990 
1991 
1992 class LFlooringDivByPowerOf2I FINAL : public LTemplateInstruction<1, 1, 0> {
1993  public:
1995  inputs_[0] = dividend;
1996  divisor_ = divisor;
1997  }
1998 
1999  LOperand* dividend() { return inputs_[0]; }
2000  int32_t divisor() const { return divisor_; }
2001 
2002  DECLARE_CONCRETE_INSTRUCTION(FlooringDivByPowerOf2I,
2003  "flooring-div-by-power-of-2-i")
2004  DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
2005 
2006  private:
2007  int32_t divisor_;
2008 };
2009 
2010 
2011 class LFlooringDivByConstI FINAL : public LTemplateInstruction<1, 1, 2> {
2012  public:
2013  LFlooringDivByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) {
2014  inputs_[0] = dividend;
2015  divisor_ = divisor;
2016  temps_[0] = temp;
2017  }
2018 
2019  LOperand* dividend() { return inputs_[0]; }
2020  int32_t divisor() const { return divisor_; }
2021  LOperand* temp() { return temps_[0]; }
2022 
2023  DECLARE_CONCRETE_INSTRUCTION(FlooringDivByConstI, "flooring-div-by-const-i")
2024  DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
2025 
2026  private:
2027  int32_t divisor_;
2028 };
2029 
2030 
2031 class LFlooringDivI FINAL : public LTemplateInstruction<1, 2, 1> {
2032  public:
2033  LFlooringDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) {
2034  inputs_[0] = dividend;
2035  inputs_[1] = divisor;
2036  temps_[0] = temp;
2037  }
2038 
2039  LOperand* dividend() { return inputs_[0]; }
2040  LOperand* divisor() { return inputs_[1]; }
2041  LOperand* temp() { return temps_[0]; }
2042 
2043  DECLARE_CONCRETE_INSTRUCTION(FlooringDivI, "flooring-div-i")
2044  DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
2045 };
2046 
2047 
2048 class LMathLog FINAL : public LUnaryMathOperation<0> {
2049  public:
2050  explicit LMathLog(LOperand* value) : LUnaryMathOperation<0>(value) { }
2051  DECLARE_CONCRETE_INSTRUCTION(MathLog, "math-log")
2052 };
2053 
2054 
2055 class LMathClz32 FINAL : public LUnaryMathOperation<0> {
2056  public:
2057  explicit LMathClz32(LOperand* value) : LUnaryMathOperation<0>(value) { }
2058  DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
2059 };
2060 
2061 
2062 class LMathMinMax FINAL : public LTemplateInstruction<1, 2, 0> {
2063  public:
2064  LMathMinMax(LOperand* left, LOperand* right) {
2065  inputs_[0] = left;
2066  inputs_[1] = right;
2067  }
2068 
2069  LOperand* left() { return inputs_[0]; }
2070  LOperand* right() { return inputs_[1]; }
2071 
2072  DECLARE_CONCRETE_INSTRUCTION(MathMinMax, "math-min-max")
2073  DECLARE_HYDROGEN_ACCESSOR(MathMinMax)
2074 };
2075 
2076 
2077 class LMathPowHalf FINAL : public LUnaryMathOperation<0> {
2078  public:
2079  explicit LMathPowHalf(LOperand* value) : LUnaryMathOperation<0>(value) { }
2080  DECLARE_CONCRETE_INSTRUCTION(MathPowHalf, "math-pow-half")
2081 };
2082 
2083 
2084 // Math.round with an integer result.
2085 class LMathRoundD FINAL : public LUnaryMathOperation<0> {
2086  public:
2087  explicit LMathRoundD(LOperand* value)
2088  : LUnaryMathOperation<0>(value) {
2089  }
2090 
2091  DECLARE_CONCRETE_INSTRUCTION(MathRoundD, "math-round-d")
2092 };
2093 
2094 
2095 // Math.round with an integer result.
2096 class LMathRoundI FINAL : public LUnaryMathOperation<1> {
2097  public:
2099  : LUnaryMathOperation<1>(value) {
2100  temps_[0] = temp1;
2101  }
2102 
2103  LOperand* temp1() { return temps_[0]; }
2104 
2105  DECLARE_CONCRETE_INSTRUCTION(MathRoundI, "math-round-i")
2106 };
2107 
2108 
2109 class LMathFround FINAL : public LUnaryMathOperation<0> {
2110  public:
2111  explicit LMathFround(LOperand* value) : LUnaryMathOperation<0>(value) {}
2112 
2113  DECLARE_CONCRETE_INSTRUCTION(MathFround, "math-fround")
2114 };
2115 
2116 
2117 class LMathSqrt FINAL : public LUnaryMathOperation<0> {
2118  public:
2119  explicit LMathSqrt(LOperand* value) : LUnaryMathOperation<0>(value) { }
2120  DECLARE_CONCRETE_INSTRUCTION(MathSqrt, "math-sqrt")
2121 };
2122 
2123 
2124 class LModByPowerOf2I FINAL : public LTemplateInstruction<1, 1, 0> {
2125  public:
2126  LModByPowerOf2I(LOperand* dividend, int32_t divisor) {
2127  inputs_[0] = dividend;
2128  divisor_ = divisor;
2129  }
2130 
2131  LOperand* dividend() { return inputs_[0]; }
2132  int32_t divisor() const { return divisor_; }
2133 
2134  DECLARE_CONCRETE_INSTRUCTION(ModByPowerOf2I, "mod-by-power-of-2-i")
2136 
2137  private:
2138  int32_t divisor_;
2139 };
2140 
2141 
2142 class LModByConstI FINAL : public LTemplateInstruction<1, 1, 1> {
2143  public:
2144  LModByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) {
2145  inputs_[0] = dividend;
2146  divisor_ = divisor;
2147  temps_[0] = temp;
2148  }
2149 
2150  LOperand* dividend() { return inputs_[0]; }
2151  int32_t divisor() const { return divisor_; }
2152  LOperand* temp() { return temps_[0]; }
2153 
2154  DECLARE_CONCRETE_INSTRUCTION(ModByConstI, "mod-by-const-i")
2156 
2157  private:
2158  int32_t divisor_;
2159 };
2160 
2161 
2162 class LModI FINAL : public LTemplateInstruction<1, 2, 0> {
2163  public:
2164  LModI(LOperand* left, LOperand* right) {
2165  inputs_[0] = left;
2166  inputs_[1] = right;
2167  }
2168 
2169  LOperand* left() { return inputs_[0]; }
2170  LOperand* right() { return inputs_[1]; }
2171 
2172  DECLARE_CONCRETE_INSTRUCTION(ModI, "mod-i")
2174 };
2175 
2176 
2177 class LMulConstIS FINAL : public LTemplateInstruction<1, 2, 0> {
2178  public:
2179  LMulConstIS(LOperand* left, LConstantOperand* right) {
2180  inputs_[0] = left;
2181  inputs_[1] = right;
2182  }
2183 
2184  LOperand* left() { return inputs_[0]; }
2185  LConstantOperand* right() { return LConstantOperand::cast(inputs_[1]); }
2186 
2187  DECLARE_CONCRETE_INSTRUCTION(MulConstIS, "mul-const-i-s")
2189 };
2190 
2191 
2192 class LMulI FINAL : public LTemplateInstruction<1, 2, 0> {
2193  public:
2194  LMulI(LOperand* left, LOperand* right) {
2195  inputs_[0] = left;
2196  inputs_[1] = right;
2197  }
2198 
2199  LOperand* left() { return inputs_[0]; }
2200  LOperand* right() { return inputs_[1]; }
2201 
2202  DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-i")
2204 };
2205 
2206 
2207 class LMulS FINAL : public LTemplateInstruction<1, 2, 0> {
2208  public:
2209  LMulS(LOperand* left, LOperand* right) {
2210  inputs_[0] = left;
2211  inputs_[1] = right;
2212  }
2213 
2214  LOperand* left() { return inputs_[0]; }
2215  LOperand* right() { return inputs_[1]; }
2216 
2217  DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-s")
2219 };
2220 
2221 
2222 class LNumberTagD FINAL : public LTemplateInstruction<1, 1, 2> {
2223  public:
2224  LNumberTagD(LOperand* value, LOperand* temp1, LOperand* temp2) {
2225  inputs_[0] = value;
2226  temps_[0] = temp1;
2227  temps_[1] = temp2;
2228  }
2229 
2230  LOperand* value() { return inputs_[0]; }
2231  LOperand* temp1() { return temps_[0]; }
2232  LOperand* temp2() { return temps_[1]; }
2233 
2234  DECLARE_CONCRETE_INSTRUCTION(NumberTagD, "number-tag-d")
2236 };
2237 
2238 
2239 class LNumberTagU FINAL : public LTemplateInstruction<1, 1, 2> {
2240  public:
2241  explicit LNumberTagU(LOperand* value,
2242  LOperand* temp1,
2243  LOperand* temp2) {
2244  inputs_[0] = value;
2245  temps_[0] = temp1;
2246  temps_[1] = temp2;
2247  }
2248 
2249  LOperand* value() { return inputs_[0]; }
2250  LOperand* temp1() { return temps_[0]; }
2251  LOperand* temp2() { return temps_[1]; }
2252 
2253  DECLARE_CONCRETE_INSTRUCTION(NumberTagU, "number-tag-u")
2254 };
2255 
2256 
2257 class LNumberUntagD FINAL : public LTemplateInstruction<1, 1, 1> {
2258  public:
2260  inputs_[0] = value;
2261  temps_[0] = temp;
2262  }
2263 
2264  LOperand* value() { return inputs_[0]; }
2265 
2266  LOperand* temp() { return temps_[0]; }
2267 
2268  DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag")
2270 };
2271 
2272 
2273 class LParameter FINAL : public LTemplateInstruction<1, 0, 0> {
2274  public:
2275  virtual bool HasInterestingComment(LCodeGen* gen) const { return false; }
2276  DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
2277 };
2278 
2279 
2280 class LPower FINAL : public LTemplateInstruction<1, 2, 0> {
2281  public:
2282  LPower(LOperand* left, LOperand* right) {
2283  inputs_[0] = left;
2284  inputs_[1] = right;
2285  }
2286 
2287  LOperand* left() { return inputs_[0]; }
2288  LOperand* right() { return inputs_[1]; }
2289 
2290  DECLARE_CONCRETE_INSTRUCTION(Power, "power")
2292 };
2293 
2294 
2295 class LPreparePushArguments FINAL : public LTemplateInstruction<0, 0, 0> {
2296  public:
2297  explicit LPreparePushArguments(int argc) : argc_(argc) {}
2298 
2299  inline int argc() const { return argc_; }
2300 
2301  DECLARE_CONCRETE_INSTRUCTION(PreparePushArguments, "prepare-push-arguments")
2302 
2303  protected:
2304  int argc_;
2305 };
2306 
2307 
2308 class LPushArguments FINAL : public LTemplateResultInstruction<0> {
2309  public:
2310  explicit LPushArguments(Zone* zone,
2311  int capacity = kRecommendedMaxPushedArgs)
2312  : zone_(zone), inputs_(capacity, zone) {}
2313 
2314  LOperand* argument(int i) { return inputs_[i]; }
2315  int ArgumentCount() const { return inputs_.length(); }
2316 
2317  void AddArgument(LOperand* arg) { inputs_.Add(arg, zone_); }
2318 
2319  DECLARE_CONCRETE_INSTRUCTION(PushArguments, "push-arguments")
2320 
2321  // It is better to limit the number of arguments pushed simultaneously to
2322  // avoid pressure on the register allocator.
2323  static const int kRecommendedMaxPushedArgs = 4;
2324  bool ShouldSplitPush() const {
2325  return inputs_.length() >= kRecommendedMaxPushedArgs;
2326  }
2327 
2328  protected:
2330  ZoneList<LOperand*> inputs_;
2331 
2332  private:
2333  // Iterator support.
2334  virtual int InputCount() FINAL OVERRIDE { return inputs_.length(); }
2335  virtual LOperand* InputAt(int i) FINAL OVERRIDE { return inputs_[i]; }
2336 
2337  virtual int TempCount() FINAL OVERRIDE { return 0; }
2338  virtual LOperand* TempAt(int i) FINAL OVERRIDE { return NULL; }
2339 };
2340 
2341 
2342 class LRegExpLiteral FINAL : public LTemplateInstruction<1, 1, 0> {
2343  public:
2344  explicit LRegExpLiteral(LOperand* context) {
2345  inputs_[0] = context;
2346  }
2347 
2348  LOperand* context() { return inputs_[0]; }
2349 
2350  DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp-literal")
2351  DECLARE_HYDROGEN_ACCESSOR(RegExpLiteral)
2352 };
2353 
2354 
2355 class LReturn FINAL : public LTemplateInstruction<0, 3, 0> {
2356  public:
2357  LReturn(LOperand* value, LOperand* context, LOperand* parameter_count) {
2358  inputs_[0] = value;
2359  inputs_[1] = context;
2360  inputs_[2] = parameter_count;
2361  }
2362 
2363  LOperand* value() { return inputs_[0]; }
2364  LOperand* parameter_count() { return inputs_[2]; }
2365 
2367  return parameter_count()->IsConstantOperand();
2368  }
2369  LConstantOperand* constant_parameter_count() {
2370  DCHECK(has_constant_parameter_count());
2371  return LConstantOperand::cast(parameter_count());
2372  }
2373 
2374  DECLARE_CONCRETE_INSTRUCTION(Return, "return")
2375 };
2376 
2377 
2378 class LSeqStringGetChar FINAL : public LTemplateInstruction<1, 2, 1> {
2379  public:
2381  LOperand* index,
2382  LOperand* temp) {
2383  inputs_[0] = string;
2384  inputs_[1] = index;
2385  temps_[0] = temp;
2386  }
2387 
2388  LOperand* string() { return inputs_[0]; }
2389  LOperand* index() { return inputs_[1]; }
2390  LOperand* temp() { return temps_[0]; }
2391 
2392  DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar, "seq-string-get-char")
2393  DECLARE_HYDROGEN_ACCESSOR(SeqStringGetChar)
2394 };
2395 
2396 
2397 class LSeqStringSetChar FINAL : public LTemplateInstruction<1, 4, 1> {
2398  public:
2400  LOperand* string,
2401  LOperand* index,
2402  LOperand* value,
2403  LOperand* temp) {
2404  inputs_[0] = context;
2405  inputs_[1] = string;
2406  inputs_[2] = index;
2407  inputs_[3] = value;
2408  temps_[0] = temp;
2409  }
2410 
2411  LOperand* context() { return inputs_[0]; }
2412  LOperand* string() { return inputs_[1]; }
2413  LOperand* index() { return inputs_[2]; }
2414  LOperand* value() { return inputs_[3]; }
2415  LOperand* temp() { return temps_[0]; }
2416 
2417  DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar, "seq-string-set-char")
2418  DECLARE_HYDROGEN_ACCESSOR(SeqStringSetChar)
2419 };
2420 
2421 
2422 class LSmiTag FINAL : public LTemplateInstruction<1, 1, 0> {
2423  public:
2424  explicit LSmiTag(LOperand* value) {
2425  inputs_[0] = value;
2426  }
2427 
2428  LOperand* value() { return inputs_[0]; }
2429 
2430  DECLARE_CONCRETE_INSTRUCTION(SmiTag, "smi-tag")
2432 };
2433 
2434 
2435 class LSmiUntag FINAL : public LTemplateInstruction<1, 1, 0> {
2436  public:
2437  LSmiUntag(LOperand* value, bool needs_check)
2438  : needs_check_(needs_check) {
2439  inputs_[0] = value;
2440  }
2441 
2442  LOperand* value() { return inputs_[0]; }
2443  bool needs_check() const { return needs_check_; }
2444 
2445  DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
2446 
2447  private:
2448  bool needs_check_;
2449 };
2450 
2451 
2452 class LStackCheck FINAL : public LTemplateInstruction<0, 1, 0> {
2453  public:
2454  explicit LStackCheck(LOperand* context) {
2455  inputs_[0] = context;
2456  }
2457 
2458  LOperand* context() { return inputs_[0]; }
2459 
2460  DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack-check")
2461  DECLARE_HYDROGEN_ACCESSOR(StackCheck)
2462 
2463  Label* done_label() { return &done_label_; }
2464 
2465  private:
2466  Label done_label_;
2467 };
2468 
2469 
2470 template<int T>
2471 class LStoreKeyed : public LTemplateInstruction<0, 3, T> {
2472  public:
2473  LStoreKeyed(LOperand* elements, LOperand* key, LOperand* value) {
2474  this->inputs_[0] = elements;
2475  this->inputs_[1] = key;
2476  this->inputs_[2] = value;
2477  }
2478 
2479  bool is_external() const { return this->hydrogen()->is_external(); }
2480  bool is_fixed_typed_array() const {
2481  return hydrogen()->is_fixed_typed_array();
2482  }
2483  bool is_typed_elements() const {
2484  return is_external() || is_fixed_typed_array();
2485  }
2486  LOperand* elements() { return this->inputs_[0]; }
2487  LOperand* key() { return this->inputs_[1]; }
2488  LOperand* value() { return this->inputs_[2]; }
2490  return this->hydrogen()->elements_kind();
2491  }
2492 
2494  if (hydrogen()->value()->IsAdd() || hydrogen()->value()->IsSub() ||
2495  hydrogen()->value()->IsMul() || hydrogen()->value()->IsDiv()) {
2496  return false;
2497  }
2498  return this->hydrogen()->NeedsCanonicalization();
2499  }
2500  uint32_t base_offset() const { return this->hydrogen()->base_offset(); }
2501 
2502  void PrintDataTo(StringStream* stream) OVERRIDE {
2503  this->elements()->PrintTo(stream);
2504  stream->Add("[");
2505  this->key()->PrintTo(stream);
2506  if (this->base_offset() != 0) {
2507  stream->Add(" + %d] <-", this->base_offset());
2508  } else {
2509  stream->Add("] <- ");
2510  }
2511 
2512  if (this->value() == NULL) {
2513  DCHECK(hydrogen()->IsConstantHoleStore() &&
2514  hydrogen()->value()->representation().IsDouble());
2515  stream->Add("<the hole(nan)>");
2516  } else {
2517  this->value()->PrintTo(stream);
2518  }
2519  }
2520 
2521  DECLARE_HYDROGEN_ACCESSOR(StoreKeyed)
2522 };
2523 
2524 
2525 class LStoreKeyedExternal FINAL : public LStoreKeyed<1> {
2526  public:
2528  LOperand* temp) :
2529  LStoreKeyed<1>(elements, key, value) {
2530  temps_[0] = temp;
2531  }
2532 
2533  LOperand* temp() { return temps_[0]; }
2534 
2535  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedExternal, "store-keyed-external")
2536 };
2537 
2538 
2539 class LStoreKeyedFixed FINAL : public LStoreKeyed<1> {
2540  public:
2541  LStoreKeyedFixed(LOperand* elements, LOperand* key, LOperand* value,
2542  LOperand* temp) :
2543  LStoreKeyed<1>(elements, key, value) {
2544  temps_[0] = temp;
2545  }
2546 
2547  LOperand* temp() { return temps_[0]; }
2548 
2549  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFixed, "store-keyed-fixed")
2550 };
2551 
2552 
2553 class LStoreKeyedFixedDouble FINAL : public LStoreKeyed<1> {
2554  public:
2556  LOperand* temp) :
2557  LStoreKeyed<1>(elements, key, value) {
2558  temps_[0] = temp;
2559  }
2560 
2561  LOperand* temp() { return temps_[0]; }
2562 
2563  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFixedDouble,
2564  "store-keyed-fixed-double")
2565 };
2566 
2567 
2568 class LStoreKeyedGeneric FINAL : public LTemplateInstruction<0, 4, 0> {
2569  public:
2571  LOperand* obj,
2572  LOperand* key,
2573  LOperand* value) {
2574  inputs_[0] = context;
2575  inputs_[1] = obj;
2576  inputs_[2] = key;
2577  inputs_[3] = value;
2578  }
2579 
2580  LOperand* context() { return inputs_[0]; }
2581  LOperand* object() { return inputs_[1]; }
2582  LOperand* key() { return inputs_[2]; }
2583  LOperand* value() { return inputs_[3]; }
2584 
2585  DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic")
2586  DECLARE_HYDROGEN_ACCESSOR(StoreKeyedGeneric)
2587 
2588  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
2589 
2590  StrictMode strict_mode() { return hydrogen()->strict_mode(); }
2591 };
2592 
2593 
2594 class LStoreNamedField FINAL : public LTemplateInstruction<0, 2, 2> {
2595  public:
2597  LOperand* temp0, LOperand* temp1) {
2598  inputs_[0] = object;
2599  inputs_[1] = value;
2600  temps_[0] = temp0;
2601  temps_[1] = temp1;
2602  }
2603 
2604  LOperand* object() { return inputs_[0]; }
2605  LOperand* value() { return inputs_[1]; }
2606  LOperand* temp0() { return temps_[0]; }
2607  LOperand* temp1() { return temps_[1]; }
2608 
2609  DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field")
2610  DECLARE_HYDROGEN_ACCESSOR(StoreNamedField)
2611 
2612  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
2613 
2614  Representation representation() const {
2615  return hydrogen()->field_representation();
2616  }
2617 };
2618 
2619 
2620 class LStoreNamedGeneric FINAL: public LTemplateInstruction<0, 3, 0> {
2621  public:
2622  LStoreNamedGeneric(LOperand* context, LOperand* object, LOperand* value) {
2623  inputs_[0] = context;
2624  inputs_[1] = object;
2625  inputs_[2] = value;
2626  }
2627 
2628  LOperand* context() { return inputs_[0]; }
2629  LOperand* object() { return inputs_[1]; }
2630  LOperand* value() { return inputs_[2]; }
2631 
2632  DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic")
2633  DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric)
2634 
2635  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
2636 
2637  Handle<Object> name() const { return hydrogen()->name(); }
2638  StrictMode strict_mode() { return hydrogen()->strict_mode(); }
2639 };
2640 
2641 
2642 class LStringAdd FINAL : public LTemplateInstruction<1, 3, 0> {
2643  public:
2644  LStringAdd(LOperand* context, LOperand* left, LOperand* right) {
2645  inputs_[0] = context;
2646  inputs_[1] = left;
2647  inputs_[2] = right;
2648  }
2649 
2650  LOperand* context() { return inputs_[0]; }
2651  LOperand* left() { return inputs_[1]; }
2652  LOperand* right() { return inputs_[2]; }
2653 
2654  DECLARE_CONCRETE_INSTRUCTION(StringAdd, "string-add")
2655  DECLARE_HYDROGEN_ACCESSOR(StringAdd)
2656 };
2657 
2658 
2659 
2660 class LStringCharCodeAt FINAL : public LTemplateInstruction<1, 3, 0> {
2661  public:
2662  LStringCharCodeAt(LOperand* context, LOperand* string, LOperand* index) {
2663  inputs_[0] = context;
2664  inputs_[1] = string;
2665  inputs_[2] = index;
2666  }
2667 
2668  LOperand* context() { return inputs_[0]; }
2669  LOperand* string() { return inputs_[1]; }
2670  LOperand* index() { return inputs_[2]; }
2671 
2672  DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string-char-code-at")
2673  DECLARE_HYDROGEN_ACCESSOR(StringCharCodeAt)
2674 };
2675 
2676 
2677 class LStringCharFromCode FINAL : public LTemplateInstruction<1, 2, 0> {
2678  public:
2679  LStringCharFromCode(LOperand* context, LOperand* char_code) {
2680  inputs_[0] = context;
2681  inputs_[1] = char_code;
2682  }
2683 
2684  LOperand* context() { return inputs_[0]; }
2685  LOperand* char_code() { return inputs_[1]; }
2686 
2687  DECLARE_CONCRETE_INSTRUCTION(StringCharFromCode, "string-char-from-code")
2688  DECLARE_HYDROGEN_ACCESSOR(StringCharFromCode)
2689 };
2690 
2691 
2692 class LStringCompareAndBranch FINAL : public LControlInstruction<3, 0> {
2693  public:
2695  inputs_[0] = context;
2696  inputs_[1] = left;
2697  inputs_[2] = right;
2698  }
2699 
2700  LOperand* context() { return inputs_[0]; }
2701  LOperand* left() { return inputs_[1]; }
2702  LOperand* right() { return inputs_[2]; }
2703 
2704  DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch,
2705  "string-compare-and-branch")
2706  DECLARE_HYDROGEN_ACCESSOR(StringCompareAndBranch)
2707 
2708  Token::Value op() const { return hydrogen()->token(); }
2709 
2710  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
2711 };
2712 
2713 
2714 // Truncating conversion from a tagged value to an int32.
2715 class LTaggedToI FINAL : public LTemplateInstruction<1, 1, 2> {
2716  public:
2717  explicit LTaggedToI(LOperand* value, LOperand* temp1, LOperand* temp2) {
2718  inputs_[0] = value;
2719  temps_[0] = temp1;
2720  temps_[1] = temp2;
2721  }
2722 
2723  LOperand* value() { return inputs_[0]; }
2724  LOperand* temp1() { return temps_[0]; }
2725  LOperand* temp2() { return temps_[1]; }
2726 
2727  DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i")
2729 
2730  bool truncating() { return hydrogen()->CanTruncateToInt32(); }
2731 };
2732 
2733 
2734 class LShiftI FINAL : public LTemplateInstruction<1, 2, 0> {
2735  public:
2736  LShiftI(Token::Value op, LOperand* left, LOperand* right, bool can_deopt)
2737  : op_(op), can_deopt_(can_deopt) {
2738  inputs_[0] = left;
2739  inputs_[1] = right;
2740  }
2741 
2742  Token::Value op() const { return op_; }
2743  LOperand* left() { return inputs_[0]; }
2744  LOperand* right() { return inputs_[1]; }
2745  bool can_deopt() const { return can_deopt_; }
2746 
2747  DECLARE_CONCRETE_INSTRUCTION(ShiftI, "shift-i")
2748 
2749  private:
2750  Token::Value op_;
2751  bool can_deopt_;
2752 };
2753 
2754 
2755 class LShiftS FINAL : public LTemplateInstruction<1, 2, 0> {
2756  public:
2757  LShiftS(Token::Value op, LOperand* left, LOperand* right, bool can_deopt)
2758  : op_(op), can_deopt_(can_deopt) {
2759  inputs_[0] = left;
2760  inputs_[1] = right;
2761  }
2762 
2763  Token::Value op() const { return op_; }
2764  LOperand* left() { return inputs_[0]; }
2765  LOperand* right() { return inputs_[1]; }
2766  bool can_deopt() const { return can_deopt_; }
2767 
2768  DECLARE_CONCRETE_INSTRUCTION(ShiftS, "shift-s")
2769 
2770  private:
2771  Token::Value op_;
2772  bool can_deopt_;
2773 };
2774 
2775 
2776 class LStoreCodeEntry FINAL: public LTemplateInstruction<0, 2, 1> {
2777  public:
2778  LStoreCodeEntry(LOperand* function, LOperand* code_object,
2779  LOperand* temp) {
2780  inputs_[0] = function;
2781  inputs_[1] = code_object;
2782  temps_[0] = temp;
2783  }
2784 
2785  LOperand* function() { return inputs_[0]; }
2786  LOperand* code_object() { return inputs_[1]; }
2787  LOperand* temp() { return temps_[0]; }
2788 
2789  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
2790 
2791  DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry, "store-code-entry")
2792  DECLARE_HYDROGEN_ACCESSOR(StoreCodeEntry)
2793 };
2794 
2795 
2796 class LStoreContextSlot FINAL : public LTemplateInstruction<0, 2, 1> {
2797  public:
2798  LStoreContextSlot(LOperand* context, LOperand* value, LOperand* temp) {
2799  inputs_[0] = context;
2800  inputs_[1] = value;
2801  temps_[0] = temp;
2802  }
2803 
2804  LOperand* context() { return inputs_[0]; }
2805  LOperand* value() { return inputs_[1]; }
2806  LOperand* temp() { return temps_[0]; }
2807 
2808  DECLARE_CONCRETE_INSTRUCTION(StoreContextSlot, "store-context-slot")
2809  DECLARE_HYDROGEN_ACCESSOR(StoreContextSlot)
2810 
2811  int slot_index() { return hydrogen()->slot_index(); }
2812 
2813  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
2814 };
2815 
2816 
2817 class LStoreGlobalCell FINAL : public LTemplateInstruction<0, 1, 2> {
2818  public:
2819  LStoreGlobalCell(LOperand* value, LOperand* temp1, LOperand* temp2) {
2820  inputs_[0] = value;
2821  temps_[0] = temp1;
2822  temps_[1] = temp2;
2823  }
2824 
2825  LOperand* value() { return inputs_[0]; }
2826  LOperand* temp1() { return temps_[0]; }
2827  LOperand* temp2() { return temps_[1]; }
2828 
2829  DECLARE_CONCRETE_INSTRUCTION(StoreGlobalCell, "store-global-cell")
2830  DECLARE_HYDROGEN_ACCESSOR(StoreGlobalCell)
2831 };
2832 
2833 
2834 class LSubI FINAL : public LTemplateInstruction<1, 2, 0> {
2835  public:
2836  LSubI(LOperand* left, LOperand* right)
2837  : shift_(NO_SHIFT), shift_amount_(0) {
2838  inputs_[0] = left;
2839  inputs_[1] = right;
2840  }
2841 
2842  LSubI(LOperand* left, LOperand* right, Shift shift, LOperand* shift_amount)
2843  : shift_(shift), shift_amount_(shift_amount) {
2844  inputs_[0] = left;
2845  inputs_[1] = right;
2846  }
2847 
2848  LOperand* left() { return inputs_[0]; }
2849  LOperand* right() { return inputs_[1]; }
2850 
2851  Shift shift() const { return shift_; }
2852  LOperand* shift_amount() const { return shift_amount_; }
2853 
2854  DECLARE_CONCRETE_INSTRUCTION(SubI, "sub-i")
2856 
2857  protected:
2858  Shift shift_;
2859  LOperand* shift_amount_;
2860 };
2861 
2862 
2863 class LSubS: public LTemplateInstruction<1, 2, 0> {
2864  public:
2865  LSubS(LOperand* left, LOperand* right) {
2866  inputs_[0] = left;
2867  inputs_[1] = right;
2868  }
2869 
2870  LOperand* left() { return inputs_[0]; }
2871  LOperand* right() { return inputs_[1]; }
2872 
2873  DECLARE_CONCRETE_INSTRUCTION(SubS, "sub-s")
2875 };
2876 
2877 
2878 class LThisFunction FINAL : public LTemplateInstruction<1, 0, 0> {
2879  public:
2880  DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function")
2881  DECLARE_HYDROGEN_ACCESSOR(ThisFunction)
2882 };
2883 
2884 
2885 class LToFastProperties FINAL : public LTemplateInstruction<1, 1, 0> {
2886  public:
2887  explicit LToFastProperties(LOperand* value) {
2888  inputs_[0] = value;
2889  }
2890 
2891  LOperand* value() { return inputs_[0]; }
2892 
2893  DECLARE_CONCRETE_INSTRUCTION(ToFastProperties, "to-fast-properties")
2894  DECLARE_HYDROGEN_ACCESSOR(ToFastProperties)
2895 };
2896 
2897 
2898 class LTransitionElementsKind FINAL : public LTemplateInstruction<0, 2, 2> {
2899  public:
2901  LOperand* context,
2902  LOperand* temp1,
2903  LOperand* temp2) {
2904  inputs_[0] = object;
2905  inputs_[1] = context;
2906  temps_[0] = temp1;
2907  temps_[1] = temp2;
2908  }
2909 
2910  LOperand* object() { return inputs_[0]; }
2911  LOperand* context() { return inputs_[1]; }
2912  LOperand* temp1() { return temps_[0]; }
2913  LOperand* temp2() { return temps_[1]; }
2914 
2915  DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind,
2916  "transition-elements-kind")
2917  DECLARE_HYDROGEN_ACCESSOR(TransitionElementsKind)
2918 
2919  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
2920 
2921  Handle<Map> original_map() { return hydrogen()->original_map().handle(); }
2923  return hydrogen()->transitioned_map().handle();
2924  }
2925  ElementsKind from_kind() const { return hydrogen()->from_kind(); }
2926  ElementsKind to_kind() const { return hydrogen()->to_kind(); }
2927 };
2928 
2929 
2930 class LTrapAllocationMemento FINAL : public LTemplateInstruction<0, 1, 2> {
2931  public:
2933  inputs_[0] = object;
2934  temps_[0] = temp1;
2935  temps_[1] = temp2;
2936  }
2937 
2938  LOperand* object() { return inputs_[0]; }
2939  LOperand* temp1() { return temps_[0]; }
2940  LOperand* temp2() { return temps_[1]; }
2941 
2942  DECLARE_CONCRETE_INSTRUCTION(TrapAllocationMemento, "trap-allocation-memento")
2943 };
2944 
2945 
2946 class LTruncateDoubleToIntOrSmi FINAL
2947  : public LTemplateInstruction<1, 1, 0> {
2948  public:
2950  inputs_[0] = value;
2951  }
2952 
2953  LOperand* value() { return inputs_[0]; }
2954 
2955  DECLARE_CONCRETE_INSTRUCTION(TruncateDoubleToIntOrSmi,
2956  "truncate-double-to-int-or-smi")
2957  DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
2958 
2959  bool tag_result() { return hydrogen()->representation().IsSmi(); }
2960 };
2961 
2962 
2963 class LTypeof FINAL : public LTemplateInstruction<1, 2, 0> {
2964  public:
2965  LTypeof(LOperand* context, LOperand* value) {
2966  inputs_[0] = context;
2967  inputs_[1] = value;
2968  }
2969 
2970  LOperand* context() { return inputs_[0]; }
2971  LOperand* value() { return inputs_[1]; }
2972 
2973  DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
2974 };
2975 
2976 
2977 class LTypeofIsAndBranch FINAL : public LControlInstruction<1, 2> {
2978  public:
2979  LTypeofIsAndBranch(LOperand* value, LOperand* temp1, LOperand* temp2) {
2980  inputs_[0] = value;
2981  temps_[0] = temp1;
2982  temps_[1] = temp2;
2983  }
2984 
2985  LOperand* value() { return inputs_[0]; }
2986  LOperand* temp1() { return temps_[0]; }
2987  LOperand* temp2() { return temps_[1]; }
2988 
2989  DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch, "typeof-is-and-branch")
2990  DECLARE_HYDROGEN_ACCESSOR(TypeofIsAndBranch)
2991 
2992  Handle<String> type_literal() const { return hydrogen()->type_literal(); }
2993 
2994  virtual void PrintDataTo(StringStream* stream) OVERRIDE;
2995 };
2996 
2997 
2998 class LUint32ToDouble FINAL : public LTemplateInstruction<1, 1, 0> {
2999  public:
3000  explicit LUint32ToDouble(LOperand* value) {
3001  inputs_[0] = value;
3002  }
3003 
3004  LOperand* value() { return inputs_[0]; }
3005 
3006  DECLARE_CONCRETE_INSTRUCTION(Uint32ToDouble, "uint32-to-double")
3007 };
3008 
3009 
3010 class LCheckMapValue FINAL : public LTemplateInstruction<0, 2, 1> {
3011  public:
3013  inputs_[0] = value;
3014  inputs_[1] = map;
3015  temps_[0] = temp;
3016  }
3017 
3018  LOperand* value() { return inputs_[0]; }
3019  LOperand* map() { return inputs_[1]; }
3020  LOperand* temp() { return temps_[0]; }
3021 
3022  DECLARE_CONCRETE_INSTRUCTION(CheckMapValue, "check-map-value")
3023 };
3024 
3025 
3026 class LLoadFieldByIndex FINAL : public LTemplateInstruction<1, 2, 0> {
3027  public:
3029  inputs_[0] = object;
3030  inputs_[1] = index;
3031  }
3032 
3033  LOperand* object() { return inputs_[0]; }
3034  LOperand* index() { return inputs_[1]; }
3035 
3036  DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex, "load-field-by-index")
3037 };
3038 
3039 
3040 class LStoreFrameContext: public LTemplateInstruction<0, 1, 0> {
3041  public:
3042  explicit LStoreFrameContext(LOperand* context) {
3043  inputs_[0] = context;
3044  }
3045 
3046  LOperand* context() { return inputs_[0]; }
3047 
3048  DECLARE_CONCRETE_INSTRUCTION(StoreFrameContext, "store-frame-context")
3049 };
3050 
3051 
3052 class LAllocateBlockContext: public LTemplateInstruction<1, 2, 0> {
3053  public:
3054  LAllocateBlockContext(LOperand* context, LOperand* function) {
3055  inputs_[0] = context;
3056  inputs_[1] = function;
3057  }
3058 
3059  LOperand* context() { return inputs_[0]; }
3060  LOperand* function() { return inputs_[1]; }
3061 
3062  Handle<ScopeInfo> scope_info() { return hydrogen()->scope_info(); }
3063 
3064  DECLARE_CONCRETE_INSTRUCTION(AllocateBlockContext, "allocate-block-context")
3065  DECLARE_HYDROGEN_ACCESSOR(AllocateBlockContext)
3066 };
3067 
3068 
3069 class LWrapReceiver FINAL : public LTemplateInstruction<1, 2, 0> {
3070  public:
3071  LWrapReceiver(LOperand* receiver, LOperand* function) {
3072  inputs_[0] = receiver;
3073  inputs_[1] = function;
3074  }
3075 
3076  DECLARE_CONCRETE_INSTRUCTION(WrapReceiver, "wrap-receiver")
3077  DECLARE_HYDROGEN_ACCESSOR(WrapReceiver)
3078 
3079  LOperand* receiver() { return inputs_[0]; }
3080  LOperand* function() { return inputs_[1]; }
3081 };
3082 
3083 
3084 class LChunkBuilder;
3085 class LPlatformChunk FINAL : public LChunk {
3086  public:
3087  LPlatformChunk(CompilationInfo* info, HGraph* graph)
3088  : LChunk(info, graph) { }
3089 
3092 };
3093 
3094 
3095 class LChunkBuilder FINAL : public LChunkBuilderBase {
3096  public:
3097  LChunkBuilder(CompilationInfo* info, HGraph* graph, LAllocator* allocator)
3098  : LChunkBuilderBase(info, graph),
3099  current_instruction_(NULL),
3100  current_block_(NULL),
3101  allocator_(allocator) {}
3102 
3103  // Build the sequence for the graph.
3104  LPlatformChunk* Build();
3105 
3106  // Declare methods that deal with the individual node types.
3107 #define DECLARE_DO(type) LInstruction* Do##type(H##type* node);
3109 #undef DECLARE_DO
3110 
3116  LInstruction* DoModI(HMod* instr);
3117  LInstruction* DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr);
3118  LInstruction* DoFlooringDivByConstI(HMathFloorOfDiv* instr);
3119  LInstruction* DoFlooringDivI(HMathFloorOfDiv* instr);
3120 
3121  static bool HasMagicNumberForDivision(int32_t divisor);
3122 
3123  private:
3124  // Methods for getting operands for Use / Define / Temp.
3127 
3128  // Methods for setting up define-use relationships.
3132  DoubleRegister fixed_register);
3133 
3134  // A value that is guaranteed to be allocated to a register.
3135  // The operand created by UseRegister is guaranteed to be live until the end
3136  // of the instruction. This means that register allocator will not reuse its
3137  // register for any other operand inside instruction.
3139 
3140  // The operand created by UseRegisterAndClobber is guaranteed to be live until
3141  // the end of the end of the instruction, and it may also be used as a scratch
3142  // register by the instruction implementation.
3143  //
3144  // This behaves identically to ARM's UseTempRegister. However, it is renamed
3145  // to discourage its use in ARM64, since in most cases it is better to
3146  // allocate a temporary register for the Lithium instruction.
3148 
3149  // The operand created by UseRegisterAtStart is guaranteed to be live only at
3150  // instruction start. The register allocator is free to assign the same
3151  // register to some other operand used inside instruction (i.e. temporary or
3152  // output).
3154 
3155  // An input operand in a register or a constant operand.
3158 
3159  // A constant operand.
3160  MUST_USE_RESULT LConstantOperand* UseConstant(HValue* value);
3161 
3162  // An input operand in register, stack slot or a constant operand.
3163  // Will not be moved to a register even if one is freely available.
3165 
3166  // Temporary operand that must be in a register.
3168 
3169  // Temporary operand that must be in a double register.
3171 
3173 
3174  // Temporary operand that must be in a fixed double register.
3176 
3177  // Methods for setting up define-use relationships.
3178  // Return the same instruction that they are passed.
3180  LUnallocated* result);
3183  int index);
3184 
3187  Register reg);
3189  DoubleRegister reg);
3190 
3191  enum CanDeoptimize { CAN_DEOPTIMIZE_EAGERLY, CANNOT_DEOPTIMIZE_EAGERLY };
3192 
3193  // By default we assume that instruction sequences generated for calls
3194  // cannot deoptimize eagerly and we do not attach environment to this
3195  // instruction.
3197  LInstruction* instr,
3198  HInstruction* hinstr,
3199  CanDeoptimize can_deoptimize = CANNOT_DEOPTIMIZE_EAGERLY);
3200 
3203 
3205  void AddInstruction(LInstruction* instr, HInstruction* current);
3206  void DoBasicBlock(HBasicBlock* block);
3207 
3209  return HConstant::cast(constant)->Integer32Value() & 0x1f;
3210  }
3211  bool LikelyFitsImmField(HInstruction* instr, int imm) {
3212  if (instr->IsAdd() || instr->IsSub()) {
3213  return Assembler::IsImmAddSub(imm) || Assembler::IsImmAddSub(-imm);
3214  } else {
3215  DCHECK(instr->IsBitwise());
3216  unsigned unused_n, unused_imm_s, unused_imm_r;
3218  &unused_n, &unused_imm_s, &unused_imm_r);
3219  }
3220  }
3221 
3222  // Indicates if a sequence of the form
3223  // lsl x8, x9, #imm
3224  // add x0, x1, x8
3225  // can be replaced with:
3226  // add x0, x1, x9 LSL #imm
3227  // If this is not possible, the function returns NULL. Otherwise it returns a
3228  // pointer to the shift instruction that would be optimized away.
3230  HValue** left = NULL);
3231  // Checks if all uses of the shift operation can optimize it away.
3233  // Attempts to merge the binary operation and an eventual previous shift
3234  // operation into a single operation. Returns the merged instruction on
3235  // success, and NULL otherwise.
3238  HValue* left,
3240 
3245  HBinaryOperation* instr);
3246 
3247  HInstruction* current_instruction_;
3248  HBasicBlock* current_block_;
3249  LAllocator* allocator_;
3250 
3252 };
3253 
3254 #undef DECLARE_HYDROGEN_ACCESSOR
3255 #undef DECLARE_CONCRETE_INSTRUCTION
3256 
3257 } } // namespace v8::internal
3258 
3259 #endif // V8_ARM64_LITHIUM_ARM64_H_
A sandboxed execution context with its own set of built-in objects and functions.
Definition: v8.h:5443
The superclass of all JavaScript values and objects.
Definition: v8.h:1440
static bool IsImmAddSub(int64_t immediate)
static bool IsImmLogical(uint64_t value, unsigned width, unsigned *n, unsigned *imm_s, unsigned *imm_r)
static U update(U previous, T value)
Definition: utils.h:223
static T decode(U value)
Definition: utils.h:228
Source to read snapshot and builtins files from.
Definition: lithium-arm.h:372
LInstructionGap(HBasicBlock *block)
LCallJSFunction(LOperand *function)
LAddE(LOperand *left, LOperand *right)
Smi * index() const
LSmiUntag(LOperand *value, bool needs_check)
LInstruction * DoDivByPowerOf2I(HDiv *instr)
LCheckSmi(LOperand *value)
DECLARE_CONCRETE_INSTRUCTION(TruncateDoubleToIntOrSmi, "truncate-double-to-int-or-smi") bool tag_result()
LOperand * temp_vector()
bool LikelyFitsImmField(HInstruction *instr, int imm)
LBoundsCheck(LOperand *index, LOperand *length)
DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch, "is-undetectable-and-branch") virtual void PrintDataTo(StringStream *stream) OVERRIDE
virtual LOperand * TempAt(int i) FINAL OVERRIDE
MUST_USE_RESULT LUnallocated * TempRegister()
LMathRoundI(LOperand *value, LOperand *temp1)
LIsSmiAndBranch(LOperand *value)
LDivByPowerOf2I(LOperand *dividend, int32_t divisor)
LOperand * unclamped()
LUint32ToDouble(LOperand *value)
LInstruction * DoShiftedBinaryOp(HBinaryOperation *instr, HValue *left, HBitwiseBinaryOperation *shift)
LModByPowerOf2I(LOperand *dividend, int32_t divisor)
LInstanceOfKnownGlobal(LOperand *context, LOperand *value)
LStringCharCodeAt(LOperand *context, LOperand *string, LOperand *index)
LInstruction * DoArithmeticT(Token::Value op, HBinaryOperation *instr)
LTransitionElementsKind(LOperand *object, LOperand *context, LOperand *temp1, LOperand *temp2)
LPower(LOperand *left, LOperand *right)
LSeqStringSetChar(LOperand *context, LOperand *string, LOperand *index, LOperand *value, LOperand *temp)
LStringCompareAndBranch(LOperand *context, LOperand *left, LOperand *right)
MUST_USE_RESULT LUnallocated * TempDoubleRegister()
LInnerAllocatedObject(LOperand *base_object, LOperand *offset)
LCmpObjectEqAndBranch(LOperand *left, LOperand *right)
LInstruction * DoFlooringDivByPowerOf2I(HMathFloorOfDiv *instr)
LMathAbs(LOperand *value)
virtual Opcode opcode() const OVERRIDE
LOperand * shift_amount() const
LStoreNamedGeneric(LOperand *context, LOperand *object, LOperand *value)
LMathClz32(LOperand *value)
LMathMinMax(LOperand *left, LOperand *right)
LConstructDouble(LOperand *hi, LOperand *lo)
LShiftI(Token::Value op, LOperand *left, LOperand *right, bool can_deopt)
LLoadContextSlot(LOperand *context)
LIsConstructCallAndBranch(LOperand *temp1, LOperand *temp2)
CallInterfaceDescriptor descriptor()
ElementsKind to_kind() const
virtual void PrintDataTo(StringStream *stream) OVERRIDE
LAddS(LOperand *left, LOperand *right)
LInstruction * DefineSameAsFirst(LTemplateResultInstruction< 1 > *instr)
LBitI(LOperand *left, LOperand *right)
LDoubleBits(LOperand *value)
LSubI(LOperand *left, LOperand *right, Shift shift, LOperand *shift_amount)
LSmiTag(LOperand *value)
LDeclareGlobals(LOperand *context)
LIsUndetectableAndBranch(LOperand *value, LOperand *temp)
virtual MUST_USE_RESULT LOperand * UseAny(HValue *value)
LOperand * argument(int i)
virtual void CompileToNative(LCodeGen *generator) OVERRIDE
LWrapReceiver(LOperand *receiver, LOperand *function)
LApplyArguments(LOperand *function, LOperand *receiver, LOperand *length, LOperand *elements)
LCheckInstanceType(LOperand *value, LOperand *temp)
LStringAdd(LOperand *context, LOperand *left, LOperand *right)
LStoreNamedField(LOperand *object, LOperand *value, LOperand *temp0, LOperand *temp1)
bool has_constant_parameter_count()
LStoreKeyedFixedDouble(LOperand *elements, LOperand *key, LOperand *value, LOperand *temp)
SaveFPRegsMode save_doubles() const
LInteger32ToDouble(LOperand *value)
virtual int TempCount() FINAL OVERRIDE
LForInCacheArray(LOperand *map)
LCmpT(LOperand *context, LOperand *left, LOperand *right)
LLabel * replacement() const
LCompareMinusZeroAndBranch(LOperand *value, LOperand *temp)
LOperand * value()
LCmpMapAndBranch(LOperand *value, LOperand *temp)
LDummyUse(LOperand *value)
LInstruction * DefineFixedDouble(LTemplateResultInstruction< 1 > *instr, DoubleRegister reg)
DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch, "has-instance-type-and-branch") virtual void PrintDataTo(StringStream *stream) OVERRIDE
LInstruction * DoModByPowerOf2I(HMod *instr)
LInstruction * AssignEnvironment(LInstruction *instr)
LLoadNamedField(LOperand *object)
LUnallocated * ToUnallocated(DoubleRegister reg)
LBitI(LOperand *left, LOperand *right, Shift shift, LOperand *shift_amount)
LAddI(LOperand *left, LOperand *right)
LDateField(LOperand *date, Smi *index)
LStoreKeyedFixed(LOperand *elements, LOperand *key, LOperand *value, LOperand *temp)
LInstruction * Define(LTemplateResultInstruction< 1 > *instr, LUnallocated *result)
virtual bool HasInterestingComment(LCodeGen *gen) const
LPushArguments(Zone *zone, int capacity=kRecommendedMaxPushedArgs)
bool ShiftCanBeOptimizedAway(HBitwiseBinaryOperation *shift)
LOperand * elements()
LInstruction * AssignPointerMap(LInstruction *instr)
LDoubleToIntOrSmi(LOperand *value)
LIsStringAndBranch(LOperand *value, LOperand *temp)
LGoto(HBasicBlock *block)
LCallNew(LOperand *context, LOperand *constructor)
LStackCheck(LOperand *context)
LOperand * char_code()
LAllocate(LOperand *context, LOperand *size, LOperand *temp1, LOperand *temp2, LOperand *temp3)
LLoadFieldByIndex(LOperand *object, LOperand *index)
virtual LOperand * InputAt(int i) FINAL OVERRIDE
virtual bool IsControl() const OVERRIDE
LArgumentsLength(LOperand *elements)
LModI(LOperand *left, LOperand *right)
LPreparePushArguments(int argc)
LMathFround(LOperand *value)
LLoadNamedGeneric(LOperand *context, LOperand *object, LOperand *vector)
MUST_USE_RESULT LOperand * UseFixedDouble(HValue *value, DoubleRegister fixed_register)
LOperand * receiver()
LArithmeticT(Token::Value op, LOperand *context, LOperand *left, LOperand *right)
LShiftS(Token::Value op, LOperand *left, LOperand *right, bool can_deopt)
LLoadKeyedGeneric(LOperand *context, LOperand *object, LOperand *key, LOperand *vector)
LGetCachedArrayIndex(LOperand *value)
int32_t divisor() const
int JSShiftAmountFromHConstant(HValue *constant)
LClampTToUint8(LOperand *unclamped, LOperand *temp1)
LOperand * GetNextSpillSlot(RegisterKind kind)
LOperand * double_temp1()
LConstantOperand * constant_parameter_count()
LCallNewArray(LOperand *context, LOperand *constructor)
LFlooringDivI(LOperand *dividend, LOperand *divisor, LOperand *temp)
DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch, "class-of-test-and-branch") virtual void PrintDataTo(StringStream *stream) OVERRIDE
LBitS(LOperand *left, LOperand *right)
LOperand * context()
LOperand * dividend()
bool can_deopt() const
void DoBasicBlock(HBasicBlock *block)
LForInPrepareMap(LOperand *context, LOperand *object)
LMapEnumLength(LOperand *value)
LInstruction * DefineAsSpilled(LTemplateResultInstruction< 1 > *instr, int index)
Token::Value op() const
LOperand * offset() const
MUST_USE_RESULT LOperand * UseRegisterAtStart(HValue *value)
LInstruction * DoDivI(HBinaryOperation *instr)
LStoreGlobalCell(LOperand *value, LOperand *temp1, LOperand *temp2)
LInvokeFunction(LOperand *context, LOperand *function)
LSubI(LOperand *left, LOperand *right)
LOperand * temp3()
LInstruction * DoFlooringDivByConstI(HMathFloorOfDiv *instr)
LMulI(LOperand *left, LOperand *right)
LLabel(HBasicBlock *block)
bool HasReplacement() const
LInstruction * DoModByConstI(HMod *instr)
MUST_USE_RESULT LOperand * Use(HValue *value, LUnallocated *operand)
LCheckValue(LOperand *value)
LStringCharFromCode(LOperand *context, LOperand *char_code)
LInstruction * DoShift(Token::Value op, HBitwiseBinaryOperation *instr)
LOperand * index()
LStoreKeyedExternal(LOperand *elements, LOperand *key, LOperand *value, LOperand *temp)
LInstruction * DoArithmeticD(Token::Value op, HArithmeticBinaryOperation *instr)
LStoreKeyedGeneric(LOperand *context, LOperand *obj, LOperand *key, LOperand *value)
virtual int InputCount() FINAL OVERRIDE
DISALLOW_COPY_AND_ASSIGN(LChunkBuilder)
LMathExp(LOperand *value, LOperand *double_temp1, LOperand *temp1, LOperand *temp2, LOperand *temp3)
LOperand * temp1()
DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind, "transition-elements-kind") virtual void PrintDataTo(StringStream *stream) OVERRIDE
LMathFloorD(LOperand *value)
LHasCachedArrayIndexAndBranch(LOperand *value, LOperand *temp)
LCheckMaps(LOperand *value=NULL, LOperand *temp=NULL)
LMulS(LOperand *left, LOperand *right)
static bool HasMagicNumberForDivision(int32_t divisor)
LCallWithDescriptor(CallInterfaceDescriptor descriptor, const ZoneList< LOperand * > &operands, Zone *zone)
LOperand * global_object()
LCallRuntime(LOperand *context)
LOperand * constructor()
StrictMode strict_mode()
LStoreCodeEntry(LOperand *function, LOperand *code_object, LOperand *temp)
LLoadGlobalGeneric(LOperand *context, LOperand *global_object, LOperand *vector)
LCmpHoleAndBranchD(LOperand *object, LOperand *temp)
LPlatformChunk * Build()
MUST_USE_RESULT LOperand * UseFixed(HValue *value, Register fixed_register)
void AddArgument(LOperand *arg)
LClampDToUint8(LOperand *unclamped)
LOperand * base_object() const
LPlatformChunk(CompilationInfo *info, HGraph *graph)
LRegExpLiteral(LOperand *context)
LNumberTagD(LOperand *value, LOperand *temp1, LOperand *temp2)
virtual bool HasInterestingComment(LCodeGen *gen) const OVERRIDE
MUST_USE_RESULT LOperand * UseRegisterAndClobber(HValue *value)
bool needs_check() const
LInstruction * DoDivByConstI(HDiv *instr)
bool for_typeof() const
void VisitInstruction(HInstruction *current)
Shift shift() const
LOperand * length()
HBitwiseBinaryOperation * CanTransformToShiftedOp(HValue *val, HValue **left=NULL)
DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch, "has-cached-array-index-and-branch") virtual void PrintDataTo(StringStream *stream) OVERRIDE
MUST_USE_RESULT LOperand * UseRegister(HValue *value)
bool is_osr_entry() const
LStoreContextSlot(LOperand *context, LOperand *value, LOperand *temp)
LInstruction * TryDoOpWithShiftedRightOperand(HBinaryOperation *op)
virtual const char * Mnemonic() const OVERRIDE
LFlooringDivByConstI(LOperand *dividend, int32_t divisor, LOperand *temp)
LDivI(LOperand *dividend, LOperand *divisor, LOperand *temp)
LCallStub(LOperand *context)
LInstruction * DoFlooringDivI(HMathFloorOfDiv *instr)
LArgumentsElements(LOperand *temp)
LInstruction * DefineFixed(LTemplateResultInstruction< 1 > *instr, Register reg)
LCompareNumericAndBranch(LOperand *left, LOperand *right)
LFunctionLiteral(LOperand *context)
LMathSqrt(LOperand *value)
MUST_USE_RESULT LOperand * FixedTemp(Register reg)
LOperand * right()
int ArgumentCount() const
LBranch(LOperand *value, LOperand *temp1, LOperand *temp2)
LHasInstanceTypeAndBranch(LOperand *value, LOperand *temp)
Handle< Map > transitioned_map()
LMathLog(LOperand *value)
LMulConstIS(LOperand *left, LConstantOperand *right)
LAddI(LOperand *left, LOperand *right, Shift shift, LOperand *shift_amount)
LOperand * parameter_count()
ElementsKind from_kind() const
LReturn(LOperand *value, LOperand *context, LOperand *parameter_count)
LTruncateDoubleToIntOrSmi(LOperand *value)
LCallFunction(LOperand *context, LOperand *function)
LNumberUntagD(LOperand *value, LOperand *temp)
MUST_USE_RESULT LOperand * FixedTemp(DoubleRegister reg)
LConstantOperand * right()
MUST_USE_RESULT LConstantOperand * UseConstant(HValue *value)
LInstruction * DoModI(HMod *instr)
MUST_USE_RESULT LOperand * UseRegisterOrConstantAtStart(HValue *value)
void AddInstruction(LInstruction *instr, HInstruction *current)
LTypeofIsAndBranch(LOperand *value, LOperand *temp1, LOperand *temp2)
void set_replacement(LLabel *label)
bool is_loop_header() const
LMathFloorI(LOperand *value)
LInstanceOf(LOperand *context, LOperand *left, LOperand *right)
LFlooringDivByPowerOf2I(LOperand *dividend, int32_t divisor)
LOperand * temp2()
LCheckNonSmi(LOperand *value)
LAccessArgumentsAt(LOperand *arguments, LOperand *length, LOperand *index)
LDivByConstI(LOperand *dividend, int32_t divisor, LOperand *temp)
LCmpHoleAndBranchT(LOperand *object)
LClassOfTestAndBranch(LOperand *value, LOperand *temp1, LOperand *temp2)
LUnallocated * ToUnallocated(Register reg)
LOperand * target() const
LTypeof(LOperand *context, LOperand *value)
LTaggedToI(LOperand *value, LOperand *temp1, LOperand *temp2)
LSeqStringGetChar(LOperand *string, LOperand *index, LOperand *temp)
MUST_USE_RESULT LOperand * UseRegisterOrConstant(HValue *value)
LCheckMapValue(LOperand *value, LOperand *map, LOperand *temp)
LIsObjectAndBranch(LOperand *value, LOperand *temp1, LOperand *temp2)
LTrapAllocationMemento(LOperand *object, LOperand *temp1, LOperand *temp2)
LMathRoundD(LOperand *value)
LChunkBuilder(CompilationInfo *info, HGraph *graph, LAllocator *allocator)
LArithmeticD(Token::Value op, LOperand *left, LOperand *right)
virtual void SetDeferredLazyDeoptimizationEnvironment(LEnvironment *env) OVERRIDE
LModByConstI(LOperand *dividend, int32_t divisor, LOperand *temp)
LOperand * code_object()
LMathPowHalf(LOperand *value)
LEnvironment * GetDeferredLazyDeoptimizationEnvironment()
LClampIToUint8(LOperand *unclamped)
LOperand * divisor()
LLoadFunctionPrototype(LOperand *function, LOperand *temp)
LNumberTagU(LOperand *value, LOperand *temp1, LOperand *temp2)
int block_id() const
LInstruction * DefineAsRegister(LTemplateResultInstruction< 1 > *instr)
DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal, "instance-of-known-global") Handle< JSFunction > function() const
LToFastProperties(LOperand *value)
LTailCallThroughMegamorphicCache(LOperand *context, LOperand *receiver, LOperand *name)
LInstruction * MarkAsCall(LInstruction *instr, HInstruction *hinstr, CanDeoptimize can_deoptimize=CANNOT_DEOPTIMIZE_EAGERLY)
LAllocateBlockContext(LOperand *context, LOperand *function)
int LookupDestination(int block_id) const
Definition: lithium.cc:285
Label * GetAssemblyLabel(int block_id) const
Definition: lithium.cc:293
virtual bool IsControl() const FINAL OVERRIDE
int FalseDestination(LChunk *chunk)
HBasicBlock * SuccessorAt(int i)
Label * FalseLabel(LChunk *chunk)
int TrueDestination(LChunk *chunk)
DECLARE_HYDROGEN_ACCESSOR(ControlInstruction)
Label * TrueLabel(LChunk *chunk)
LGap(HBasicBlock *block)
virtual void PrintDataTo(StringStream *stream) OVERRIDE
static LGap * cast(LInstruction *instr)
virtual bool IsGap() const OVERRIDE
LParallelMove * GetParallelMove(InnerPosition pos)
bool IsRedundant() const
HBasicBlock * block() const
LParallelMove * GetOrCreateParallelMove(InnerPosition pos, Zone *zone)
SetOncePointer< LPointerMap > pointer_map_
Definition: lithium-arm.h:282
virtual int InputCount()=0
void set_environment(LEnvironment *env)
virtual bool HasResult() const =0
virtual void PrintDataTo(StringStream *stream)
virtual int TempCount()=0
virtual const char * Mnemonic() const =0
virtual LOperand * TempAt(int i)=0
LEnvironment * environment() const
virtual LOperand * InputAt(int i)=0
void set_hydrogen_value(HValue *value)
virtual LOperand * result() const =0
virtual void PrintTo(StringStream *stream)
virtual void SetDeferredLazyDeoptimizationEnvironment(LEnvironment *env)
HValue * hydrogen_value() const
void set_pointer_map(LPointerMap *p)
LEnvironment * environment_
Definition: lithium-arm.h:281
virtual Opcode opcode() const =0
virtual bool ClobbersDoubleRegisters(Isolate *isolate) const
virtual bool HasInterestingComment(LCodeGen *gen) const
virtual void CompileToNative(LCodeGen *generator)=0
virtual bool IsControl() const
LPointerMap * pointer_map() const
virtual bool IsGap() const
virtual void PrintOutputOperandTo(StringStream *stream)
LLoadKeyedExternal(LOperand *elements, LOperand *key, LOperand *temp)
DECLARE_CONCRETE_INSTRUCTION(LoadKeyedExternal, "load-keyed-external")
DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFixedDouble, "load-keyed-fixed-double")
LLoadKeyedFixedDouble(LOperand *elements, LOperand *key, LOperand *temp)
DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFixed, "load-keyed-fixed")
LLoadKeyedFixed(LOperand *elements, LOperand *key, LOperand *temp)
void PrintDataTo(StringStream *stream) OVERRIDE
bool is_typed_elements() const
ElementsKind elements_kind() const
LLoadKeyed(LOperand *elements, LOperand *key)
uint32_t base_offset() const
bool is_fixed_typed_array() const
LMathAbsTagged(LOperand *context, LOperand *value, LOperand *temp1, LOperand *temp2, LOperand *temp3)
LStoreFrameContext(LOperand *context)
LStoreKeyed(LOperand *elements, LOperand *key, LOperand *value)
bool is_fixed_typed_array() const
void PrintDataTo(StringStream *stream) OVERRIDE
ElementsKind elements_kind() const
uint32_t base_offset() const
LSubS(LOperand *left, LOperand *right)
EmbeddedContainer< LOperand *, I > inputs_
Definition: lithium-arm.h:311
virtual LOperand * TempAt(int i) FINAL OVERRIDE
virtual int TempCount() FINAL OVERRIDE
EmbeddedContainer< LOperand *, T > temps_
Definition: lithium-arm.h:312
virtual LOperand * InputAt(int i) FINAL OVERRIDE
virtual int InputCount() FINAL OVERRIDE
virtual bool HasResult() const FINAL OVERRIDE
EmbeddedContainer< LOperand *, R > results_
Definition: lithium-arm.h:301
BuiltinFunctionId op() const
void set(T *value)
Definition: utils.h:417
static Smi * FromInt(int value)
Definition: objects-inl.h:1321
#define OVERRIDE
#define FINAL
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf map
enable harmony numeric enable harmony object literal extensions Optimize object size
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
enable harmony numeric enable harmony object literal extensions Optimize object Array shift
#define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)
#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic)
#define DECLARE_DO(type)
#define DECLARE_PREDICATE(type)
#define DECLARE_OPCODE(type)
#define DECLARE_HYDROGEN_ACCESSOR(type)
#define DCHECK(condition)
Definition: logging.h:205
#define MUST_USE_RESULT
Definition: macros.h:266
int int32_t
Definition: unicode.cc:24
static Object * DeclareGlobals(Isolate *isolate, Handle< GlobalObject > global, Handle< String > name, Handle< Object > value, PropertyAttributes attr, bool is_var, bool is_const, bool is_function)
Definition: runtime.cc:1038
const unsigned kWRegSizeInBits
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
#define T(name, string, precedence)
Definition: token.cc:25